home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume12 / pathalias9 / part02 < prev    next >
Encoding:
Internet Message Format  |  1987-10-08  |  59.8 KB

  1. Subject:  v12i002:  Pathalias, version 9, Part02/02
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rs@uunet.UU.NET
  5.  
  6. Submitted-by: honey@CITI.UMICH.EDU (Peter Honeyman)
  7. Posting-number: Volume 12, Issue 2
  8. Archive-name: pathalias9/part02
  9.  
  10. [  This is the latest and greatest pathalias, and other tools.  It may
  11.    well be the last one peter ever works on, judging from his off-line
  12.    remarks... :-)  This version has had several bugs fixed, and has
  13.    been tested on BSD, Sun, 3B, SysV, Mac, etc.  MOST IMPORTANTLY:
  14.    it has several new features, and additions to the input syntax, that
  15.    you will need for all future UUCP maps.  Finally, had I an
  16.    irrelevant axe to grind, I'd point out that this code has no
  17.    copyright and is in the public domain.  --r$  ]
  18.  
  19. #! /bin/sh
  20. # This is a shell archive.  Remove anything before this line, then unpack
  21. # it by saving it into a file and typing "sh file".  To overwrite existing
  22. # files, type "sh file -c".  You can also feed this as standard input via
  23. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  24. # will see the following message at the end:
  25. #        "End of archive 2 (of 2)."
  26. # Contents:  addnode.c arpatxt.c mapit.c parse.y pathalias.1
  27. # Wrapped by rsalz@uunet on Mon Oct  5 22:45:12 1987
  28. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  29. if test -f addnode.c -a "${1}" != "-c" ; then 
  30.   echo shar: Will not over-write existing file \"addnode.c\"
  31. else
  32. echo shar: Extracting \"addnode.c\" \(8514 characters\)
  33. sed "s/^X//" >addnode.c <<'END_OF_addnode.c'
  34. X/* pathalias -- by steve bellovin, as told to peter honeyman */
  35. X#ifndef lint
  36. Xstatic char    *sccsid = "@(#)addnode.c    9.1 87/10/04";
  37. X#endif
  38. X
  39. X#include "def.h"
  40. X
  41. X/* exports */
  42. Xnode *addnode(), *addprivate();
  43. Xvoid alias(), hashanalyze(), fixprivate(), penalize();
  44. Xnode **Table;                /* hash table ^ priority queue */
  45. Xlong Tabsize;                /* size of Table */    
  46. X
  47. X/* imports */
  48. Xextern link *addlink();
  49. Xextern node *newnode(), **newtable();
  50. Xextern char *strsave();
  51. Xextern int Iflag, Tflag, Vflag;
  52. Xextern node **Table;
  53. Xextern long Ncount, Tabsize;
  54. Xextern char **Argv;
  55. Xextern void atrace(), die();
  56. X
  57. X/* privates */
  58. XSTATIC void crcinit(), rehash(), lowercase();
  59. XSTATIC long fold();
  60. XSTATIC long hash();
  61. XSTATIC node *isprivate();
  62. Xstatic node *Private;    /* list of private nodes in current input file */
  63. X/*
  64. X * these numbers are chosen because:
  65. X *    -> they are prime,
  66. X *    -> they are monotonic increasing,
  67. X *    -> each is a tad smaller than a multiple of 1024,
  68. X *    -> they form a fibonacci sequence (almost).
  69. X * the first point yields good hash functions, the second is used for the
  70. X * standard re-hashing implementation of open addressing, the third
  71. X * optimizes for quirks in some mallocs i have seen, and the fourth simply
  72. X * appeals to me.
  73. X */
  74. Xstatic long Primes[] = {
  75. X    1021, 2039, 3067, 5113, 8179, 13309, 21499, 34807, 56311, 0
  76. X};
  77. X
  78. Xstatic int    Tabindex;
  79. Xstatic long    Tab128;        /* Tabsize * 128 */
  80. X
  81. Xnode    *
  82. Xaddnode(name)
  83. X    register char *name;
  84. X{    register long i;
  85. X    register node *n;
  86. X
  87. X    if (Iflag)
  88. X        lowercase(name);
  89. X
  90. X    /* is it a private host? */
  91. X    n = isprivate(name);
  92. X    if (n)
  93. X        return n;
  94. X
  95. X    i = hash(name, 0);
  96. X    if (Table[i]) 
  97. X        return Table[i];
  98. X
  99. X    n = newnode();
  100. X    n->n_name = strsave(name);
  101. X    Table[i] = n;
  102. X    n->n_tloc = i;    /* essentially a back link to the table */
  103. X
  104. X    return n;
  105. X}
  106. X
  107. Xvoid
  108. Xalias(n1, n2)
  109. X    node *n1, *n2;
  110. X{
  111. X    link    *l;
  112. X
  113. X    if (ISADOMAIN(n1) && ISADOMAIN(n2)) {
  114. X        fprintf(stderr, "%s: domain alias %s = %s is illegal\n", Argv[0], n1->n_name, n2->n_name);
  115. X        return;
  116. X    }
  117. X    l = addlink(n1, n2, (Cost) 0, DEFNET, DEFDIR);
  118. X    l->l_flag |= LALIAS;
  119. X    l = addlink(n2, n1, (Cost) 0, DEFNET, DEFDIR);
  120. X    l->l_flag |= LALIAS;
  121. X    if (Tflag)
  122. X        atrace(n1, n2);
  123. X}
  124. X
  125. X/*
  126. X * fold a string into a long int.  31 bit crc (from andrew appel).
  127. X * the crc table is computed at run time by crcinit() -- we could
  128. X * precompute, but it takes 1 clock tick on a 750.
  129. X *
  130. X * This fast table calculation works only if POLY is a prime polynomial
  131. X * in the field of integers modulo 2.  Since the coefficients of a
  132. X * 32-bit polynomail won't fit in a 32-bit word, the high-order bit is
  133. X * implicit.  IT MUST ALSO BE THE CASE that the coefficients of orders
  134. X * 31 down to 25 are zero.  Happily, we have candidates, from
  135. X * E. J.  Watson, "Primitive Polynomials (Mod 2)", Math. Comp. 16 (1962):
  136. X *    x^32 + x^7 + x^5 + x^3 + x^2 + x^1 + x^0
  137. X *    x^31 + x^3 + x^0
  138. X *
  139. X * We reverse the bits to get:
  140. X *    111101010000000000000000000000001 but drop the last 1
  141. X *         f   5   0   0   0   0   0   0
  142. X *    010010000000000000000000000000001 ditto, for 31-bit crc
  143. X *       4   8   0   0   0   0   0   0
  144. X */
  145. X
  146. X#define POLY32 0xf5000000    /* 32-bit polynomial */
  147. X#define POLY31 0x48000000    /* 31-bit polynomial */
  148. X#define POLY POLY31    /* use 31-bit to avoid sign problems */
  149. X
  150. Xstatic long CrcTable[128];
  151. X
  152. XSTATIC void
  153. Xcrcinit()
  154. X{    register int i,j;
  155. X    register long sum;
  156. X
  157. X    for (i = 0; i < 128; i++) {
  158. X        sum = 0;
  159. X        for (j = 7-1; j >= 0; --j)
  160. X            if (i & (1 << j))
  161. X                sum ^= POLY >> j;
  162. X        CrcTable[i] = sum;
  163. X    }
  164. X}
  165. X
  166. XSTATIC long
  167. Xfold(s)
  168. X    register char *s;
  169. X{    register long sum = 0;
  170. X    register int c;
  171. X
  172. X    while (c = *s++)
  173. X        sum = (sum >> 7) ^ CrcTable[(sum ^ c) & 0x7f];
  174. X    return sum;
  175. X}
  176. X
  177. X
  178. X#define HASH1(n) ((n) % Tabsize);
  179. X#define HASH2(n) (Tabsize - 2 - ((n) % (Tabsize-2)))    /* sedgewick */
  180. X
  181. X/*
  182. X * when alpha is 0.79, there should be 2 probes per access (gonnet).
  183. X * use long constant to force promotion.  Tab128 biases HIGHWATER by
  184. X * 128/100 for reduction in strength in isfull().
  185. X */
  186. X#define HIGHWATER    79L
  187. X#define isfull(n)    ((n) * 128 >= Tab128)
  188. X    
  189. XSTATIC long
  190. Xhash(name, unique)
  191. X    char *name;
  192. X{    register long probe;
  193. X    register long hash2;
  194. X    register node *n;
  195. X
  196. X    if (isfull(Ncount)) {
  197. X        if (Tabsize == 0) {        /* first time */
  198. X            crcinit();
  199. X            Tabindex = 0;
  200. X            Tabsize = Primes[0];
  201. X            Table = newtable(Tabsize);
  202. X            Tab128 = (HIGHWATER * Tabsize * 128L)/100L;
  203. X        } else
  204. X            rehash();        /* more, more! */
  205. X    }
  206. X
  207. X    probe = fold(name);
  208. X    hash2 = HASH2(probe);
  209. X    probe = HASH1(probe);
  210. X
  211. X    /*
  212. X     * probe the hash table.
  213. X     * if unique is set, we require a fresh slot.
  214. X     * otherwise, use double hashing to find either
  215. X     *  (1) an empty slot, or
  216. X     *  (2) a non-private copy of this host name
  217. X     */
  218. X    while ((n = Table[probe]) != 0) {
  219. X        if (unique)
  220. X            goto skip;
  221. X        if (n->n_flag & ISPRIVATE)
  222. X            goto skip;
  223. X        if (strcmp(n->n_name, name) == 0)
  224. X            break;            /* this is it! */
  225. Xskip:
  226. X        probe -= hash2;
  227. X        if (probe < 0)
  228. X            probe += Tabsize;
  229. X    }
  230. X    return probe;
  231. X}
  232. X
  233. XSTATIC void
  234. Xrehash()
  235. X{    register node **otable, **optr;
  236. X    register long probe;
  237. X    long osize;
  238. X
  239. X#ifdef DEBUG
  240. X    hashanalyze();
  241. X#endif
  242. X    optr = Table + Tabsize - 1;    /* ptr to last */
  243. X    otable = Table;
  244. X    osize = Tabsize;
  245. X    Tabsize = Primes[++Tabindex];
  246. X    if (Tabsize == 0)
  247. X        die("too many hosts");    /* need more prime numbers */
  248. X    vprintf(stderr, "rehash into %d\n", Tabsize);
  249. X    Table = newtable(Tabsize);
  250. X    Tab128 = (HIGHWATER * Tabsize * 128L)/100L;
  251. X
  252. X    do {
  253. X        if (*optr == 0)
  254. X            continue;    /* empty slot in old table */
  255. X        probe = hash((*optr)->n_name, (int) ((*optr)->n_flag & ISPRIVATE));
  256. X        if (Table[probe] != 0)
  257. X            die("rehash error");
  258. X        Table[probe] = *optr;
  259. X        (*optr)->n_tloc = probe;
  260. X    } while (optr-- > otable);
  261. X    freetable(otable, osize);
  262. X}
  263. X
  264. Xvoid
  265. Xhashanalyze()
  266. X{     long    probe, hash2;
  267. X    int    count, i, collision[8];
  268. X    int    longest = 0, total = 0, slots = 0, longprobe = 0;
  269. X    int    nslots = sizeof(collision)/sizeof(collision[0]);
  270. X
  271. X    if (!Vflag)
  272. X        return;
  273. X
  274. X    strclear((char *) collision, sizeof(collision));
  275. X    for (i = 0; i < Tabsize; i++) {
  276. X        if (Table[i] == 0)
  277. X            continue;
  278. X        /* private hosts too hard to account for ... */
  279. X        if (Table[i]->n_flag & ISPRIVATE)
  280. X            continue;
  281. X        count = 1;
  282. X        probe = fold(Table[i]->n_name);
  283. X        /* don't change the order of the next two lines */
  284. X        hash2 = HASH2(probe);
  285. X        probe = HASH1(probe);
  286. X        /* thank you! */
  287. X        while (Table[probe] != 0
  288. X            && strcmp(Table[probe]->n_name, Table[i]->n_name) != 0) {
  289. X            count++;
  290. X            probe -= hash2;
  291. X            if (probe < 0)
  292. X                probe += Tabsize;
  293. X        }
  294. X        if (Table[probe] == 0)
  295. X            die("impossible hash error");
  296. X        
  297. X        total += count;
  298. X        slots++;
  299. X        if (count > longest) {
  300. X            longest = count;
  301. X            longprobe = i;
  302. X        }
  303. X        if (count >= nslots)
  304. X            count = 0;
  305. X        collision[count]++;
  306. X    }
  307. X    for (i = 1; i < nslots; i++)
  308. X        if (collision[i])
  309. X            fprintf(stderr, "%d chains: %d (%ld%%)\n",
  310. X                i, collision[i], (collision[i] * 100L)/ slots);
  311. X        if (collision[0])
  312. X            fprintf(stderr, "> %d chains: %d (%ld%%)\n",
  313. X                nslots - 1, collision[0],
  314. X                (collision[0] * 100L)/ slots);
  315. X    fprintf(stderr, "%2.2f probes per access, longest chain: %d, %s\n",
  316. X        (double) total / slots, longest, Table[longprobe]->n_name);
  317. X    if (Vflag < 2)
  318. X        return;
  319. X    probe = fold(Table[longprobe]->n_name);
  320. X    hash2 = HASH2(probe);
  321. X    probe = HASH1(probe);
  322. X    while (Table[probe] != 0
  323. X        && strcmp(Table[probe]->n_name, Table[longprobe]->n_name) != 0) {
  324. X        fprintf(stderr, "%5d %s\n", probe, Table[probe]->n_name);
  325. X        probe -= hash2;
  326. X        if (probe < 0)
  327. X            probe += Tabsize;
  328. X    }
  329. X    fprintf(stderr, "%5d %s\n", probe, Table[probe]->n_name);
  330. X    
  331. X}
  332. X
  333. X/* convert to lower case in place */
  334. XSTATIC void
  335. Xlowercase(s)
  336. X    register char *s;
  337. X{
  338. X    do {
  339. X        if (isupper(*s))
  340. X            *s -= 'A' - 'a';    /* ASCII */
  341. X    } while (*s++);
  342. X}
  343. X
  344. X/*
  345. X * this might need change if privates catch on
  346. X */
  347. XSTATIC node *
  348. Xisprivate(name)
  349. X    register char *name;
  350. X{    register node *n;
  351. X
  352. X    for (n = Private; n != 0; n = n->n_private)
  353. X        if (strcmp(name, n->n_name) == 0)
  354. X            return n;
  355. X    return 0;
  356. X}
  357. X
  358. Xvoid
  359. Xfixprivate()
  360. X{    register node *n, *next;
  361. X    register long i;
  362. X
  363. X    for (n = Private; n != 0; n = next) {
  364. X        n->n_flag |= ISPRIVATE;        /* overkill, but safe */
  365. X        i = hash(n->n_name, 1);
  366. X        if (Table[i] != 0)
  367. X            die("impossible private node error");
  368. X    
  369. X        Table[i] = n;
  370. X        n->n_tloc = i;    /* essentially a back link to the table */
  371. X        next = n->n_private;
  372. X        n->n_private = 0;    /* clear for later use */
  373. X    }
  374. X    Private = 0;
  375. X}
  376. X
  377. Xnode *
  378. Xaddprivate(name)
  379. X    register char *name;
  380. X{    register node *n;
  381. X
  382. X    if (Iflag)
  383. X        lowercase(name);
  384. X    if ((n = isprivate(name)) != 0)
  385. X        return n;
  386. X
  387. X    n = newnode();
  388. X    n->n_name = strsave(name);
  389. X    n->n_private = Private;
  390. X    Private = n;
  391. X    return n;
  392. X}
  393. X
  394. Xvoid
  395. Xpenalize(name, cost)
  396. X    char *name;
  397. X    Cost cost;
  398. X{    node *n;
  399. X
  400. X    if (Iflag)
  401. X        lowercase(name);
  402. X    n = addnode(name);
  403. X    n->n_cost += cost;    /* cumulative */
  404. X}
  405. END_OF_addnode.c
  406. if test 8514 -ne `wc -c <addnode.c`; then
  407.     echo shar: \"addnode.c\" unpacked with wrong size!
  408. fi
  409. # end of overwriting check
  410. fi
  411. if test -f arpatxt.c -a "${1}" != "-c" ; then 
  412.   echo shar: Will not over-write existing file \"arpatxt.c\"
  413. else
  414. echo shar: Extracting \"arpatxt.c\" \(12317 characters\)
  415. sed "s/^X//" >arpatxt.c <<'END_OF_arpatxt.c'
  416. X#ifndef lint
  417. Xstatic char *sccsid = "@(#)arpatxt.c    9.1 87/10/04";
  418. X#endif
  419. X
  420. X/*
  421. X * convert hosts.txt into pathalias format.
  422. X *
  423. X * alias rule: "host.dom.ain,nickname.arpa,..." -> host = nickname, ...
  424. X */
  425. X
  426. X/* remove the next line for standard or research unix */
  427. X#define BSD
  428. X
  429. X#ifdef BSD
  430. X#define strchr index
  431. X#endif /* BSD */
  432. X
  433. X#include <stdio.h>
  434. X#include <ctype.h>
  435. X
  436. Xtypedef struct node node;
  437. X
  438. Xstruct node {
  439. X    node *child;    /* subdomain or member host */
  440. X    node *parent;    /* parent domain */
  441. X    node *next;    /* sibling in domain tree or host list */
  442. X    char *name;
  443. X    node *alias;
  444. X    node *bucket;
  445. X    node *gateway;
  446. X    int  flag;
  447. X};
  448. X
  449. Xnode *Top;
  450. Xint Atflag;
  451. Xint Fflag, Iflag;
  452. Xchar *DotArpa = ".ARPA";
  453. Xchar Fname[256], *Fstart;
  454. X
  455. Xnode *newnode(), *find();
  456. Xchar *strsave(), *lowercase();
  457. Xvoid crcinit();
  458. Xlong fold();
  459. XFILE *mkfile();
  460. X
  461. Xextern char *malloc(), *strchr(), *calloc(), *gets(), *strcpy(), *fgets();
  462. Xextern FILE *fopen();
  463. X
  464. X#define ISADOMAIN(n) ((n) && *((n)->name) == '.')
  465. X
  466. X/* for node.flag */
  467. X#define COLLISION 1
  468. X
  469. X/* for formatprint() */
  470. X#define PRIVATE        0
  471. X#define HOSTS        1
  472. X#define SUBDOMAINS    2
  473. X
  474. X/* for usage() */
  475. X#define USAGE "usage: %s [-i@] [-g gateway] [-p privatefile] [-f | -d directory] [file ...]\n"
  476. X
  477. Xmain(argc, argv)
  478. X    char **argv;
  479. X{    int c;
  480. X    char *progname;
  481. X    extern char *optarg;
  482. X    extern int optind;
  483. X
  484. X    if ((progname = strchr(argv[0], '/')) != 0)
  485. X        progname++;
  486. X    else
  487. X        progname = argv[0];
  488. X    crcinit();
  489. X
  490. X    Top = newnode();    /* needed for adding gateways */
  491. X    while ((c = getopt(argc, argv, "d:fg:ip:@")) != EOF)
  492. X        switch(c) {
  493. X        case 'd':
  494. X            strcpy(Fname, optarg);
  495. X            break;
  496. X        case 'f':    /* filter mode -- write on stdout */
  497. X            Fflag++;
  498. X            break;
  499. X        case 'g':
  500. X            gateway(optarg);
  501. X            break;
  502. X        case 'i':
  503. X            Iflag++;
  504. X            break;
  505. X        case 'p':
  506. X            readprivates(optarg);
  507. X            break;
  508. X        case '@':
  509. X            Atflag++;
  510. X            break;
  511. X        default:
  512. X            usage(progname);
  513. X        }
  514. X
  515. X    if (Fflag && *Fname)
  516. X        usage(progname);
  517. X    if (Iflag)
  518. X        (void) lowercase(DotArpa);
  519. X    if (Top->gateway == 0)
  520. X        fprintf(stderr, "%s: warning: no gateway to top level domains\n", progname);
  521. X
  522. X    Fstart = Fname + strlen(Fname);
  523. X    if (Fstart != Fname) {
  524. X        *Fstart++ = '/';
  525. X        *Fstart = 0;
  526. X    }
  527. X    /* should do the mkdir here instead of the shell script ...*/
  528. X        
  529. X    Top->name = "internet";
  530. X    if (optind == argc)
  531. X        scan();
  532. X    else for ( ; optind < argc; optind++) {
  533. X        if (freopen(argv[optind], "r", stdin) == 0) {
  534. X            perror(argv[optind]);
  535. X            continue;
  536. X        }
  537. X        scan();
  538. X    }
  539. X    merge();
  540. X    dump(Top);
  541. X    return 0;
  542. X}
  543. X
  544. Xscan()
  545. X{    static first;
  546. X    char buf0[BUFSIZ], buf1[BUFSIZ], buf2[BUFSIZ];
  547. X
  548. X    if (first++ == 0)
  549. X        (void) re_comp("^HOST.*SMTP");
  550. X    while (gets(buf0) != 0) {
  551. X        if (re_exec(buf0) == 0)
  552. X            continue;
  553. X        if (sscanf(buf0, "HOST : %[^:] : %[^: ]", buf1, buf2) != 2)
  554. X            continue;
  555. X        if (Iflag)
  556. X            (void) lowercase(buf2);
  557. X        insert(buf2);
  558. X    }
  559. X}
  560. X/*
  561. X * format of private file:
  562. X *    one per line, optionally followed by white space and comments
  563. X *    line starting with # is comment
  564. X */
  565. Xreadprivates(pfile)
  566. X    char *pfile;
  567. X{    FILE *f;
  568. X    node *n;
  569. X    char buf[BUFSIZ], *bptr;
  570. X
  571. X    if ((f = fopen(pfile, "r")) == 0) {
  572. X        perror(pfile);
  573. X        return;
  574. X    }
  575. X    while (fgets(buf, BUFSIZ, f) != 0) {
  576. X        if (*buf == '#')
  577. X            continue;
  578. X        if ((bptr = strchr(buf, ' ')) != 0)
  579. X            *bptr = 0;
  580. X        if ((bptr = strchr(buf, '\t')) != 0)
  581. X            *bptr = 0;
  582. X        if (*buf == 0)
  583. X            continue;
  584. X        n = newnode();
  585. X        n->name = strsave(buf);
  586. X        hash(n);
  587. X    }
  588. X    (void) fclose(f);
  589. X}
  590. Xusage(progname)
  591. X    char *progname;
  592. X{
  593. X    fprintf(stderr, USAGE, progname);
  594. X    exit(1);
  595. X}
  596. Xdumpgateways(ndom, f)
  597. X    node *ndom;
  598. X    FILE *f;
  599. X{    node *n;
  600. X
  601. X    for (n = ndom->gateway; n; n = n->next) {
  602. X        fprintf(f, "%s ", n->name);
  603. X        if (Atflag)
  604. X            putc('@', f);
  605. X        fprintf(f, "%s(%s)\t# gateway\n", ndom->name,
  606. X                ndom == Top ? "DEDICATED" : "LOCAL");
  607. X    }
  608. X}
  609. X
  610. Xgateway(buf)
  611. X    char *buf;
  612. X{    node *n, *dom;
  613. X    char *dot;
  614. X
  615. X    dot = strchr(buf, '.');
  616. X    if (dot) {
  617. X        dom = find(dot);
  618. X        *dot = 0;
  619. X    } else
  620. X        dom = Top;
  621. X
  622. X    n = newnode();
  623. X    n->name = strsave(buf);
  624. X    n->next = dom->gateway;
  625. X    dom->gateway = n;
  626. X}
  627. X    
  628. Xinsert(buf)
  629. X    char *buf;
  630. X{    char host[BUFSIZ], *hptr, *dot;
  631. X    node *n;
  632. X
  633. X    for (hptr = host; *hptr = *buf++; hptr++)
  634. X        if (*hptr == ',')
  635. X            break;
  636. X
  637. X    if (*hptr == ',')
  638. X        *hptr = 0;
  639. X    else
  640. X        buf = 0;    /* no aliases */
  641. X
  642. X    if ((dot = strchr(host, '.')) == 0)
  643. X        abort();    /* can't happen */
  644. X    
  645. X    if (strcmp(dot, DotArpa) == 0)
  646. X        buf = 0;        /* no aliases */
  647. X
  648. X    n = find(dot);
  649. X    *dot = 0;
  650. X
  651. X    addchild(n, host, buf);
  652. X}
  653. X
  654. Xnode *
  655. Xfind(domain)
  656. X    char *domain;
  657. X{    char *dot;
  658. X    node *parent, *child;
  659. X
  660. X    if (domain == 0)
  661. X        return Top;
  662. X    if ((dot = strchr(domain+1, '.')) != 0) {
  663. X        parent = find(dot);
  664. X        *dot = 0;
  665. X    } else
  666. X        parent = Top;
  667. X
  668. X    for (child = parent->child; child; child = child->next)
  669. X        if (strcmp(domain, child->name) == 0)
  670. X            break;
  671. X    if (child == 0) {
  672. X        child = newnode();
  673. X        child->next = parent->child;
  674. X        parent->child = child;
  675. X        child->parent = parent;
  676. X        child->name = strsave(domain);
  677. X    }
  678. X    return child;
  679. X}
  680. X
  681. Xnode *
  682. Xnewnode()
  683. X{
  684. X    node *n;
  685. X
  686. X    if ((n = (node *) calloc(1, sizeof(node))) == 0)
  687. X        abort();
  688. X    return n;
  689. X}
  690. X
  691. Xchar *
  692. Xstrsave(buf)
  693. X    char *buf;
  694. X{    char *mstr;
  695. X
  696. X    if ((mstr = malloc(strlen(buf)+1)) == 0)
  697. X        abort();
  698. X    strcpy(mstr, buf);
  699. X    return mstr;
  700. X}
  701. X
  702. Xaddchild(n, host, aliases)
  703. X    node *n;
  704. X    char *host, *aliases;
  705. X{    node *child;
  706. X
  707. X    /* check for dups?  nah! */
  708. X    child = newnode();
  709. X    child->name = strsave(host);
  710. X    child->parent = n;
  711. X    child->next = n->child;
  712. X    makealiases(child, aliases);
  713. X    n->child = child;
  714. X}
  715. X
  716. X/* yer basic tree walk */
  717. Xdump(n)
  718. X    node *n;
  719. X{    node *child;
  720. X    FILE *f;
  721. X    int hadprivates = 0;
  722. X
  723. X    if (n->child == 0)
  724. X        return;
  725. X
  726. X    f = mkfile(n);
  727. X
  728. X    if (n != Top && ! ISADOMAIN(n))
  729. X        abort();
  730. X
  731. X    hadprivates = domprint(n, f);
  732. X    dumpgateways(n, f);
  733. X    if (hadprivates || n == Top)
  734. X        fputs("private {}\n", f);    /* end scope of privates */
  735. X    if (!Fflag)
  736. X        (void) fclose(f);
  737. X    else
  738. X        putc('\n', f);
  739. X    for (child = n->child; child; child = child->next)
  740. X        dump(child);
  741. X}
  742. X
  743. Xqcmp(a, b)
  744. X    node **a, **b;
  745. X{
  746. X    return strcmp((*a)->name, (*b)->name);
  747. X}
  748. X
  749. Xdomprint(n, f)
  750. X    node *n;
  751. X    FILE *f;
  752. X{    node *table[10240], *child, *alias;
  753. X    char *cost = 0;
  754. X    int nelem, i, rval = 0;
  755. X
  756. X    /* dump private definitions */
  757. X    /* sort hosts and aliases in table */
  758. X    i = 0;
  759. X    for (child = n->child; child; child = child->next) {
  760. X        table[i++] = child;
  761. X        for (alias = child->alias; alias; alias = alias->next)
  762. X            table[i++] = alias;
  763. X    }
  764. X
  765. X    qsort((char *) table, i, sizeof(table[0]), qcmp);
  766. X    formatprint(f, table, i, PRIVATE, "private", cost);
  767. X
  768. X    /* rval == 0 IFF no privates */
  769. X    while (i-- > 0)
  770. X        if (table[i]->flag & COLLISION) {
  771. X            rval = 1;
  772. X            break;
  773. X        }
  774. X
  775. X    /* dump domains and aliases */
  776. X    /* sort hosts (only) in table */
  777. X    i = 0;
  778. X    for (child = n->child; child; child = child->next)
  779. X        table[i++] = child;
  780. X    qsort((char *) table, i, sizeof(table[0]), qcmp);
  781. X
  782. X    /* cost is DEDICATED for hosts in top-level domains, LOCAL o.w. */
  783. X    if (n->parent == Top && strchr(n->name + 1, '.') == 0)
  784. X        cost = "DEDICATED";
  785. X    else
  786. X        cost = "LOCAL";
  787. X    formatprint(f, table, i, HOSTS, n->name, cost);
  788. X
  789. X    formatprint(f, table, i, SUBDOMAINS, n->name, "0");
  790. X
  791. X    /* dump aliases */
  792. X    nelem = i;
  793. X    for (i = 0; i < nelem; i++) {
  794. X        if ((alias = table[i]->alias) == 0)
  795. X            continue;
  796. X        fprintf(f, "%s = %s", table[i]->name, alias->name);
  797. X        for (alias = alias->next; alias; alias = alias->next)
  798. X            fprintf(f, ", %s", alias->name);
  799. X        putc('\n', f);
  800. X    }
  801. X
  802. X    return rval;
  803. X}
  804. X
  805. X/* for debugging */
  806. Xdtable(comment, table, nelem)
  807. X    char *comment;
  808. X    node **table;
  809. X{    int    i;
  810. X
  811. X    fprintf(stderr, "\n%s\n", comment);
  812. X    for (i = 0; i < nelem; i++)
  813. X        fprintf(stderr, "%3d\t%s\n", i, table[i]->name);
  814. X}
  815. X
  816. Xformatprint(f, table, nelem, type, lhs, cost)
  817. X    FILE *f;
  818. X    node **table;
  819. X    char *lhs, *cost;
  820. X{    int i, didprint;
  821. X    char buf[128], *bptr;
  822. X
  823. X    sprintf(buf, "%s%s{" /*}*/, lhs, type == PRIVATE ? " " : " = ");
  824. X    bptr = buf + strlen(buf);
  825. X
  826. X    didprint = 0;
  827. X    for (i = 0; i < nelem; i++) {
  828. X        if (type == PRIVATE && ! (table[i]->flag & COLLISION))
  829. X            continue;
  830. X        else if (type == HOSTS && ISADOMAIN(table[i]) )
  831. X            continue;
  832. X        else if (type == SUBDOMAINS && ! ISADOMAIN(table[i]) )
  833. X            continue;
  834. X
  835. X        if ((bptr - buf) + strlen(table[i]->name) > 69) {
  836. X            *bptr = 0;
  837. X            fprintf(f, "%s\n ", buf);    /* continuation */
  838. X            bptr = buf;
  839. X        }
  840. X        sprintf(bptr, "%s, ", table[i]->name);
  841. X        bptr += strlen(bptr);
  842. X        didprint++;
  843. X    }
  844. X    *bptr = 0;
  845. X
  846. X    if ( ! didprint )
  847. X        return;
  848. X
  849. X    fprintf(f, /*{*/ "%s}", buf);
  850. X    if (type != PRIVATE)
  851. X        fprintf(f, "(%s)", cost);
  852. X    putc('\n', f);
  853. X}
  854. X
  855. XFILE *                
  856. Xmkfile(n)
  857. X    node *n;
  858. X{    node *parent;
  859. X    char *bptr;
  860. X    FILE *f;
  861. X
  862. X    /* build up the domain name in Fname[] */
  863. X    bptr = Fstart;
  864. X    if (n == Top)
  865. X        strcpy(bptr, n->name);
  866. X    else {
  867. X        strcpy(bptr, n->name + 1);    /* skip leading dot */
  868. X        bptr = bptr + strlen(bptr);
  869. X        parent = n->parent;
  870. X        while (ISADOMAIN(parent)) {
  871. X            strcpy(bptr, parent->name);
  872. X            bptr += strlen(bptr);
  873. X            parent = parent->parent;
  874. X        }
  875. X        *bptr = 0;
  876. X    }
  877. X
  878. X    /* get a stream descriptor */
  879. X    if (Fflag) {
  880. X        printf("# %s\n", Fstart);
  881. X        f = stdout;
  882. X    } else {
  883. X#ifndef BSD
  884. X        Fstart[14] = 0;
  885. X#endif
  886. X        if ((f = fopen(Fname, "w")) == 0) {
  887. X            perror(Fname);
  888. X            exit(1);
  889. X        }
  890. X    }
  891. X    if (n == Top)
  892. X        fprintf(f, "private {%s}\ndead {%s}\n", Top->name, Top->name);
  893. X    return f;
  894. X}
  895. X
  896. X/* map to lower case in place.  return parameter for convenience */
  897. Xchar *
  898. Xlowercase(buf)
  899. X    char *buf;
  900. X{    char *str;
  901. X
  902. X    for (str = buf ; *str; str++)
  903. X        if (isupper(*str))
  904. X            *str -= 'A' - 'a';
  905. X    return buf;
  906. X}
  907. X
  908. X/* get the interesting aliases, attach to n->alias */
  909. Xmakealiases(n, line)
  910. X    node *n;
  911. X    char *line;
  912. X{    char *next, *dot;
  913. X    node *a;
  914. X
  915. X    if (line == 0 || *line == 0)
  916. X        return;
  917. X
  918. X    for ( ; line; line = next) {
  919. X        next = strchr(line, ',');
  920. X        if (next)
  921. X            *next++ = 0;
  922. X        if ((dot = strchr(line, '.')) == 0)
  923. X            continue;
  924. X        if (strcmp(dot, DotArpa) != 0)
  925. X            continue;
  926. X        *dot = 0;
  927. X
  928. X        if (strcmp(n->name, line) == 0)
  929. X            continue;
  930. X
  931. X        a = newnode();
  932. X        a->name = strsave(line);
  933. X        a->next = n->alias;
  934. X        n->alias = a;
  935. X    }
  936. X}
  937. X
  938. X#define NHASH 13309
  939. Xnode *htable[NHASH];
  940. X
  941. Xmerge()
  942. X{    node *n;
  943. X
  944. X    setuniqflag(Top);
  945. X    for (n = Top->child; n; n = n->next) {
  946. X        if (n->flag & COLLISION) {
  947. X            fprintf(stderr, "illegal subdomain: %s\n", n->name);
  948. X            abort();
  949. X        }
  950. X        promote(n);
  951. X    }
  952. X}
  953. X
  954. X/*
  955. X * for domains like cc.umich.edu and cc.berkeley.edu, it's inaccurate
  956. X * to describe cc as a member of umich.edu or berkeley.edu.  (i.e., the
  957. X * lousy scoping rules for privates don't permit a clean syntax.)  so.
  958. X *
  959. X * to prevent confusion, tack on to any such domain name its parent domain
  960. X * and promote it in the tree.  e.g., make cc.umich and cc.berkeley
  961. X * subdomains of edu.
  962. X */
  963. X
  964. Xpromote(parent)
  965. X    node *parent;
  966. X{    node *prev, *child, *next;
  967. X    char buf[BUFSIZ];
  968. X
  969. X    prev = 0;
  970. X    for (child = parent->child; child; child = next) {
  971. X        next = child->next;
  972. X        if (!ISADOMAIN(child)) {
  973. X            prev = child;
  974. X            continue;
  975. X        }
  976. X        if ((child->flag & COLLISION) || child->gateway) {
  977. X            /*
  978. X             * dup domain name or gateway found.  don't bump
  979. X             * prev: this node is moving up the tree.
  980. X             */
  981. X
  982. X            /* qualify child domain name */
  983. X            sprintf(buf, "%s%s", child->name, parent->name);
  984. X            cfree(child->name);
  985. X            child->name = strsave(buf);
  986. X
  987. X            /* unlink child out of sibling chain */
  988. X            if (prev)
  989. X                prev->next = child->next;
  990. X            else
  991. X                parent->child = child->next;
  992. X
  993. X            /* link child in as peer of parent */
  994. X            child->next = parent->next;
  995. X            parent->next = child;
  996. X            child->parent = parent->parent;
  997. X
  998. X            /*
  999. X             * reset collision flag; may promote again on
  1000. X             * return to caller.
  1001. X             */
  1002. X            child->flag &= ~COLLISION;
  1003. X            hash(child);
  1004. X        } else {
  1005. X            /* this domain is uninteresting (so bump prev) */
  1006. X            promote(child);
  1007. X            prev = child;
  1008. X        }
  1009. X    }
  1010. X    
  1011. X}
  1012. X
  1013. Xsetuniqflag(n)
  1014. X    node *n;
  1015. X{    node *child, *alias;
  1016. X
  1017. X    /* mark this node in the hash table */
  1018. X    hash(n);
  1019. X    /* mark the aliases of this node */
  1020. X    for (alias = n->alias; alias; alias = alias->next)
  1021. X        hash(alias);
  1022. X    /* recursively mark this node's children */
  1023. X    for (child = n->child; child; child = child->next)
  1024. X        setuniqflag(child);
  1025. X}
  1026. X
  1027. Xhash(n)
  1028. X    node *n;
  1029. X{    node **bucket, *b;
  1030. X
  1031. X    bucket = &htable[fold(n->name) % NHASH];
  1032. X    for (b = *bucket; b; b = b->bucket) {
  1033. X        if (strcmp(n->name, b->name) == 0) {
  1034. X            b->flag |= COLLISION;
  1035. X            n->flag |= COLLISION;
  1036. X            return;
  1037. X        }
  1038. X    }
  1039. X    n->bucket = *bucket;
  1040. X    *bucket = n;
  1041. X}
  1042. X
  1043. X/* stolen from pathalias:addnode.c, q.v. */
  1044. X#define POLY    0x48000000        /* 31-bit polynomial */
  1045. Xlong CrcTable[128];
  1046. X
  1047. Xvoid
  1048. Xcrcinit()
  1049. X{    register int i,j;
  1050. X    register long sum;
  1051. X
  1052. X    for (i = 0; i < 128; i++) {
  1053. X        sum = 0;
  1054. X        for (j = 7-1; j >= 0; --j)
  1055. X            if (i & (1 << j))
  1056. X                sum ^= POLY >> j;
  1057. X        CrcTable[i] = sum;
  1058. X    }
  1059. X}
  1060. X
  1061. Xlong
  1062. Xfold(s)
  1063. X    register char *s;
  1064. X{    register long sum = 0;
  1065. X    register int c;
  1066. X
  1067. X    while (c = *s++)
  1068. X        sum = (sum >> 7) ^ CrcTable[(sum ^ c) & 0x7f];
  1069. X    return sum;
  1070. X}
  1071. END_OF_arpatxt.c
  1072. if test 12317 -ne `wc -c <arpatxt.c`; then
  1073.     echo shar: \"arpatxt.c\" unpacked with wrong size!
  1074. fi
  1075. # end of overwriting check
  1076. fi
  1077. if test -f mapit.c -a "${1}" != "-c" ; then 
  1078.   echo shar: Will not over-write existing file \"mapit.c\"
  1079. else
  1080. echo shar: Extracting \"mapit.c\" \(13861 characters\)
  1081. sed "s/^X//" >mapit.c <<'END_OF_mapit.c'
  1082. X/* pathalias -- by steve bellovin, as told to peter honeyman */
  1083. X#ifndef lint
  1084. Xstatic char    *sccsid = "@(#)mapit.c    9.1 87/10/04";
  1085. X#endif
  1086. X
  1087. X#include "def.h"
  1088. X
  1089. X#define chkheap(i)    /* void */
  1090. X
  1091. X/* exports */
  1092. X/* invariant while mapping: Nheap < Hashpart */
  1093. Xlong Hashpart;        /* start of unreached nodes */
  1094. Xlong Nheap;        /* end of heap */
  1095. X
  1096. Xvoid mapit();
  1097. X
  1098. X/* imports */
  1099. Xextern long Nheap, Hashpart, Tabsize;
  1100. Xextern int Tflag, Vflag;
  1101. Xextern node **Table, *Home;
  1102. Xextern char *Linkout, *Graphout;
  1103. X
  1104. Xextern void freelink(), resetnodes(), printit(), dumpgraph();
  1105. Xextern void showlinks(), die();
  1106. Xextern long pack(), allocation();
  1107. Xextern link *newlink(), *addlink();
  1108. Xextern int maptrace();
  1109. Xextern node *ncopy();
  1110. X
  1111. X
  1112. X/* privates */
  1113. Xstatic long    Heaphighwater;
  1114. Xstatic link    **Heap;
  1115. X
  1116. XSTATIC void insert(), heapup(), heapdown(), heapswap(), backlinks();
  1117. XSTATIC void setheapbits(), mtracereport(), heapchildren();
  1118. XSTATIC link *min_node();
  1119. XSTATIC int dehash(), skiplink(), skipterminalalias();
  1120. XSTATIC Cost costof();
  1121. X
  1122. X/* transform the graph to a shortest-path tree by marking tree edges */
  1123. Xvoid
  1124. Xmapit()
  1125. X{    register node *n;
  1126. X    register link *l;
  1127. X    link *lparent;
  1128. X    static int firsttime = 0;
  1129. X
  1130. X    vprintf(stderr, "*** mapping\n");
  1131. X    Tflag = Tflag && Vflag;        /* tracing here only if verbose */
  1132. X    /* re-use the hash table space for the heap */
  1133. X    Heap = (link **) Table;
  1134. X    Hashpart = pack(0L, Tabsize - 1);
  1135. X
  1136. X    /* expunge penalties from -a option and make circular copy lists */
  1137. X    resetnodes();
  1138. X
  1139. X    if (firsttime++) {
  1140. X        if (Linkout && *Linkout)    /* dump cheapest links */
  1141. X            showlinks();
  1142. X        if (Graphout && *Graphout)    /* dump the edge list */
  1143. X            dumpgraph();
  1144. X    }
  1145. X
  1146. X    /* insert Home to get things started */
  1147. X    l = newlink();        /* link to get things started */
  1148. X    l->l_to = Home;
  1149. X    (void) dehash(Home);
  1150. X    insert(l);
  1151. X
  1152. X    /* main mapping loop */
  1153. Xremap:
  1154. X    Heaphighwater = Nheap;
  1155. X    while ((lparent = min_node()) != 0) {
  1156. X        chkheap(1);
  1157. X        lparent->l_flag |= LTREE;
  1158. X        n = lparent->l_to;
  1159. X        if (Tflag && maptrace(n, n))
  1160. X            fprintf(stderr, "%s -> %s mapped\n", n->n_parent->n_name, n->n_name);
  1161. X        if (n->n_flag & MAPPED)
  1162. X            die("mapped node in heap");
  1163. X        n->n_flag |= MAPPED;
  1164. X
  1165. X        /* add children to heap */
  1166. X        heapchildren(n);
  1167. X    }
  1168. X    vprintf(stderr, "heap high water mark was %d\n", Heaphighwater);
  1169. X
  1170. X    /* sanity check on implementation */
  1171. X    if (Nheap != 0)
  1172. X        die("null entry in heap");
  1173. X
  1174. X    if (Hashpart < Tabsize) {
  1175. X        /*
  1176. X         * add back links from unreachable hosts to
  1177. X         * reachable neighbors, then remap.
  1178. X         *
  1179. X         * asymptotically, this is quadratic; in
  1180. X         * practice, this is done once or twice.
  1181. X         */
  1182. X        backlinks();
  1183. X        if (Nheap)
  1184. X            goto remap;
  1185. X    }
  1186. X    if (Hashpart < Tabsize) {
  1187. X        fputs("You can't get there from here:\n", stderr);
  1188. X        for ( ; Hashpart < Tabsize; Hashpart++) {
  1189. X            fprintf(stderr, "\t%s", Table[Hashpart]->n_name);
  1190. X            if (Table[Hashpart]->n_flag & ISPRIVATE)
  1191. X                fputs(" (private)", stderr);
  1192. X            putc('\n', stderr);
  1193. X        }
  1194. X    }
  1195. X}
  1196. X
  1197. XSTATIC void
  1198. Xheapchildren(n)
  1199. X    register node *n;
  1200. X{    register link *l;
  1201. X    register node *next;
  1202. X    register int mtrace;
  1203. X    register Cost cost;
  1204. X
  1205. X    for (l = n->n_link; l; l = l->l_next) {
  1206. X
  1207. X        next = l->l_to;        /* neighboring node */
  1208. X        mtrace = Tflag && maptrace(n, next);
  1209. X
  1210. X        if (next->n_flag & MAPPED) {
  1211. X            if (mtrace)
  1212. X                mtracereport(n, l, "-\talready mapped");
  1213. X            continue;
  1214. X        }
  1215. X        if (l->l_flag & LTREE)
  1216. X            continue;
  1217. X
  1218. X        if (l->l_flag & LTERMINAL)
  1219. X            next = l->l_to = ncopy(next);
  1220. X
  1221. X        if ((n->n_flag & NTERMINAL) && (l->l_flag & LALIAS))
  1222. X            if (skipterminalalias(n, next))
  1223. X                continue;
  1224. X            else
  1225. X                next = l->l_to = ncopy(next);
  1226. X            
  1227. X
  1228. X        cost = costof(n, l);
  1229. X
  1230. X        if (skiplink(l, n, cost, mtrace))
  1231. X            continue;
  1232. X
  1233. X        /*
  1234. X         * put this link in the heap and restore the
  1235. X         * heap property.
  1236. X         */
  1237. X        if (mtrace) {
  1238. X            if (next->n_parent)
  1239. X                mtracereport(next->n_parent, l, "*\tdrop");
  1240. X            mtracereport(n, l, "+\tadd");
  1241. X        }
  1242. X        next->n_parent = n;
  1243. X        if (dehash(next) == 0) {  /* first time */
  1244. X            next->n_cost = cost;
  1245. X            insert(l);      /* insert at end */
  1246. X            heapup(l);
  1247. X        } else {
  1248. X            /* replace inferior path */
  1249. X            Heap[next->n_tloc] = l;
  1250. X            if (cost > next->n_cost) {
  1251. X                /* increase cost (gateway) */
  1252. X                next->n_cost = cost;
  1253. X                heapdown(l);
  1254. X            } else if (cost < next->n_cost) {
  1255. X                /* cheaper route */
  1256. X                next->n_cost = cost;
  1257. X
  1258. X                heapup(l);
  1259. X            }
  1260. X        }
  1261. X        setheapbits(l);
  1262. X        chkheap(1);
  1263. X
  1264. X    }
  1265. X}
  1266. X
  1267. X/* bizarro special case */
  1268. XSTATIC
  1269. Xskipterminalalias(n, next)
  1270. X    node *n, *next;
  1271. X{    node *ncp;
  1272. X
  1273. X    while (n->n_flag & NALIAS) {
  1274. X        n = n->n_parent;
  1275. X        for (ncp = n->n_copy; ncp != n; ncp = ncp->n_copy)
  1276. X            if (next == ncp)
  1277. X                return 1;
  1278. X    }
  1279. X    return 0;
  1280. X}
  1281. X
  1282. X/*
  1283. X * return 1 if we definitely don't want want this link in the
  1284. X * shortest path tree, 0 if we might want it, i.e., best so far.
  1285. X *
  1286. X * if tracing is turned on, report only if this node is being skipped.
  1287. X */
  1288. XSTATIC int
  1289. Xskiplink(l, parent, cost, trace)
  1290. X    link *l;        /* new link to this node */
  1291. X    node *parent;        /* (potential) new parent of this node */
  1292. X    register Cost cost;    /* new cost to this node */
  1293. X    int trace;        /* trace this link? */
  1294. X{    register node *n;    /* this node */
  1295. X    register link *lheap;        /* old link to this node */
  1296. X
  1297. X    n = l->l_to;
  1298. X
  1299. X    /* first time we've reached this node? */
  1300. X    if (n->n_tloc >= Hashpart)
  1301. X        return 0;
  1302. X
  1303. X    lheap = Heap[n->n_tloc];
  1304. X
  1305. X    /* examine links to nets that require gateways */
  1306. X    if (GATEWAYED(n)) {
  1307. X        /* if exactly one is a gateway, use it */
  1308. X        if ((lheap->l_flag & LGATEWAY) && !(l->l_flag & LGATEWAY)) {
  1309. X            if (trace)
  1310. X                mtracereport(parent, l, "-\told gateway");
  1311. X            return 1;    /* old is gateway */
  1312. X        }
  1313. X        if (!(lheap->l_flag & LGATEWAY) && (l->l_flag & LGATEWAY))
  1314. X            return 0;    /* new is gateway */
  1315. X
  1316. X        /* no gateway or both gateways;  resolve in standard way ... */
  1317. X    }
  1318. X
  1319. X    /* examine dup link (sanity check) */
  1320. X    if (n->n_parent == parent && ((lheap->l_flag & LDEAD) || (l->l_flag & LDEAD)))
  1321. X        die("dup dead link");
  1322. X
  1323. X    /*  examine cost */
  1324. X    if (cost < n->n_cost)
  1325. X        return 0;
  1326. X    if (cost > n->n_cost) {
  1327. X        if (trace)
  1328. X            mtracereport(parent, l, "-\tcheaper");
  1329. X        return 1;
  1330. X    }
  1331. X
  1332. X    /* all other things being equal, ask the oracle */
  1333. X    if (tiebreaker(n, parent)) {
  1334. X        if (trace)
  1335. X            mtracereport(parent, l, "-\ttiebreaker");
  1336. X        return 1;
  1337. X    }
  1338. X    return 0;
  1339. X}
  1340. X
  1341. XSTATIC Cost
  1342. Xcostof(prev, l)
  1343. X    register node *prev;
  1344. X    register link *l;
  1345. X{    register node *next;
  1346. X    register Cost cost;
  1347. X
  1348. X    if (l->l_flag & LALIAS)
  1349. X        return prev->n_cost;    /* by definition */
  1350. X
  1351. X    next = l->l_to;
  1352. X    cost = prev->n_cost + l->l_cost;    /* basic cost */
  1353. X
  1354. X    /*
  1355. X     * heuristics:
  1356. X     *    charge for a dead link.
  1357. X     *    charge for getting past a terminal edge.
  1358. X     *    charge for getting out of a dead host.
  1359. X     *    charge for getting into a gatewayed net (except at a gateway).
  1360. X     *    discourage mixing of left and right syntax when prev is a host.
  1361. X     *
  1362. X     * life was simpler when pathalias computed true shortest paths.
  1363. X     */
  1364. X    if (l->l_flag & LDEAD)                /* dead link */
  1365. X        cost += INF;
  1366. X    if (prev->n_flag & NTERMINAL)            /* terminal parent */
  1367. X        cost += INF;
  1368. X    if (DEADHOST(prev))                /* dead host */
  1369. X        cost += INF;
  1370. X    if (GATEWAYED(next) && !(l->l_flag & LGATEWAY))    /* not gateway */
  1371. X        cost += INF;
  1372. X    if (!ISANET(prev)) {                /* mixed syntax? */
  1373. X        if ((NETDIR(l) == LLEFT && (prev->n_flag & HASRIGHT))
  1374. X         || (NETDIR(l) == LRIGHT && (prev->n_flag & HASLEFT)))
  1375. X            cost += INF;
  1376. X    }
  1377. X
  1378. X    return cost;
  1379. X}
  1380. X
  1381. X/* binary heap implementation of priority queue */
  1382. X
  1383. XSTATIC void
  1384. Xinsert(l)
  1385. X    link *l;
  1386. X{    register node *n;
  1387. X
  1388. X    n = l->l_to;
  1389. X    if (n->n_flag & MAPPED)
  1390. X        die("insert mapped node");
  1391. X
  1392. X    Heap[n->n_tloc] = 0;
  1393. X    if (Heap[Nheap+1] != 0)
  1394. X        die("heap error in insert");
  1395. X    if (Nheap++ == 0) {
  1396. X        Heap[1] = l;
  1397. X        n->n_tloc = 1;
  1398. X        return;
  1399. X    }
  1400. X    if (Vflag && Nheap > Heaphighwater)
  1401. X        Heaphighwater = Nheap;    /* diagnostics */
  1402. X
  1403. X    /* insert at the end.  caller must heapup(l). */
  1404. X    Heap[Nheap] = l;
  1405. X    n->n_tloc = Nheap;
  1406. X}
  1407. X
  1408. X/*
  1409. X * "percolate" up the heap by exchanging with the parent.  as in
  1410. X * min_node(), give tiebreaker() a chance to produce better, stable
  1411. X * routes by moving nets and domains close to the root, nets closer
  1412. X * than domains.
  1413. X *
  1414. X * i know this seems obscure, but it's harmless and cheap.  trust me.
  1415. X */
  1416. XSTATIC void
  1417. Xheapup(l)
  1418. X    link *l;
  1419. X{    register long cindx, pindx;    /* child, parent indices */
  1420. X    register Cost cost;
  1421. X    register node *child, *parent;
  1422. X
  1423. X    child = l->l_to;
  1424. X
  1425. X    cost = child->n_cost;
  1426. X    for (cindx = child->n_tloc; cindx > 1; cindx = pindx) {
  1427. X        pindx = cindx / 2;
  1428. X        if (Heap[pindx] == 0)    /* sanity check */
  1429. X            die("impossible error in heapup");
  1430. X        parent = Heap[pindx]->l_to;
  1431. X        if (cost > parent->n_cost)
  1432. X            return;
  1433. X
  1434. X        /* net/domain heuristic */
  1435. X        if (cost == parent->n_cost) {
  1436. X            if (!ISANET(child))
  1437. X                return;
  1438. X            if (!ISADOMAIN(parent))
  1439. X                return;
  1440. X            if (ISADOMAIN(child))
  1441. X                return;
  1442. X        }
  1443. X        heapswap(cindx, pindx);
  1444. X    }
  1445. X}
  1446. X
  1447. X/* extract min (== Heap[1]) from heap */
  1448. XSTATIC link    *
  1449. Xmin_node()
  1450. X{    link *rval, *lastlink;
  1451. X    register link **rheap;
  1452. X
  1453. X    if (Nheap == 0)
  1454. X        return 0;
  1455. X
  1456. X    rheap = Heap;        /* in register -- heavily used */
  1457. X    rval = rheap[1];    /* return this one */
  1458. X
  1459. X    /* move last entry into root and reheap */
  1460. X    lastlink = rheap[Nheap];
  1461. X    rheap[Nheap] = 0;
  1462. X
  1463. X    if (--Nheap) {
  1464. X        rheap[1] = lastlink;
  1465. X        lastlink->l_to->n_tloc = 1;
  1466. X        heapdown(lastlink);    /* restore heap property */
  1467. X    }
  1468. X
  1469. X    return rval;
  1470. X}
  1471. X
  1472. X/*
  1473. X * swap Heap[i] with smaller child, iteratively down the tree.
  1474. X *
  1475. X * given the opportunity, attempt to place nets and domains
  1476. X * near the root.  this helps tiebreaker() shun domain routes.
  1477. X */
  1478. X
  1479. XSTATIC void
  1480. Xheapdown(l)
  1481. X    link *l;
  1482. X{    register long pindx, cindx;
  1483. X    register link **rheap = Heap;    /* in register -- heavily used */
  1484. X    node *child, *rchild, *parent;
  1485. X
  1486. X    pindx = l->l_to->n_tloc;
  1487. X    parent = rheap[pindx]->l_to;    /* invariant */
  1488. X    for ( ; (cindx = pindx * 2) <= Nheap; pindx = cindx) {
  1489. X        /* pick lhs or rhs child */
  1490. X        child = rheap[cindx]->l_to;
  1491. X        if (cindx < Nheap) {
  1492. X            /* compare with rhs child */
  1493. X            rchild = rheap[cindx+1]->l_to;
  1494. X            /*
  1495. X             * use rhs child if smaller than lhs child.
  1496. X             * if equal, use rhs if net or domain.
  1497. X             */
  1498. X            if (child->n_cost > rchild->n_cost) {
  1499. X                child = rchild;
  1500. X                cindx++;
  1501. X            } else if (child->n_cost == rchild->n_cost)
  1502. X                if (ISANET(rchild)) {
  1503. X                    child = rchild;
  1504. X                    cindx++;
  1505. X                }
  1506. X        }
  1507. X
  1508. X        /* child is the candidate for swapping */
  1509. X        if (parent->n_cost < child->n_cost)
  1510. X            break;
  1511. X
  1512. X        /*
  1513. X         * heuristics:
  1514. X         *    move nets/domains up
  1515. X         *    move nets above domains
  1516. X         */
  1517. X        if (parent->n_cost == child->n_cost) {
  1518. X            if (!ISANET(child))
  1519. X                break;
  1520. X            if (ISANET(parent) && ISADOMAIN(child))
  1521. X                break;
  1522. X        }
  1523. X
  1524. X        heapswap(pindx, cindx);
  1525. X    }
  1526. X}
  1527. X
  1528. X/* exchange Heap[i] and Heap[j] pointers */
  1529. XSTATIC void
  1530. Xheapswap(i, j)
  1531. X    long i, j;
  1532. X{    register link *temp, **rheap;
  1533. X
  1534. X    rheap = Heap;    /* heavily used -- put in register */
  1535. X    temp = rheap[i];
  1536. X    rheap[i] = rheap[j];
  1537. X    rheap[j] = temp;
  1538. X    rheap[j]->l_to->n_tloc = j;
  1539. X    rheap[i]->l_to->n_tloc = i;
  1540. X}
  1541. X
  1542. X/* return 1 if n is already de-hashed (n_tloc < Hashpart), 0 o.w. */
  1543. XSTATIC int
  1544. Xdehash(n)
  1545. X    register node *n;
  1546. X{
  1547. X    if (n->n_tloc < Hashpart)
  1548. X        return 1;
  1549. X
  1550. X    /* swap with entry in Table[Hashpart] */
  1551. X    Table[Hashpart]->n_tloc = n->n_tloc;
  1552. X    Table[n->n_tloc] = Table[Hashpart];
  1553. X    Table[Hashpart] = n;
  1554. X
  1555. X    n->n_tloc = Hashpart++;
  1556. X    return 0;
  1557. X}
  1558. X
  1559. XSTATIC void
  1560. Xbacklinks()
  1561. X{    register link *l;
  1562. X    register node *n, *parent;
  1563. X    node *nomap, *ncp;
  1564. X    long i;
  1565. X
  1566. X    for (i = Hashpart; i < Tabsize; i++) {
  1567. X        nomap = Table[i];
  1568. X        for (ncp = nomap->n_copy; ncp != nomap; ncp = ncp->n_copy) {
  1569. X            if (ncp->n_flag & MAPPED) {
  1570. X                dehash(nomap);
  1571. X                Table[nomap->n_tloc] = 0;
  1572. X                nomap->n_tloc = 0;
  1573. X                goto nexti;
  1574. X            }
  1575. X        }
  1576. X
  1577. X        /* TODO: simplify this */        
  1578. X        parent = 0;
  1579. X        for (l = nomap->n_link; l; l = l->l_next) {
  1580. X            n = l->l_to;
  1581. X            if (!(n->n_flag & MAPPED))
  1582. X                continue;
  1583. X            if (parent == 0) {
  1584. X                parent = n;
  1585. X                continue;
  1586. X            }
  1587. X            if (n->n_cost > parent->n_cost)
  1588. X                continue;
  1589. X            if (n->n_cost == parent->n_cost) {
  1590. X                nomap->n_parent = parent;
  1591. X                if (tiebreaker(nomap, n))
  1592. X                    continue;
  1593. X            }
  1594. X            parent = n;
  1595. X        }
  1596. X        if (parent == 0)
  1597. X            continue;
  1598. X        (void) dehash(nomap);
  1599. X        l = addlink(parent, nomap, INF, DEFNET, DEFDIR);
  1600. X        nomap->n_parent = parent;
  1601. X        nomap->n_cost = costof(parent, l);
  1602. X        insert(l);
  1603. X        heapup(l);
  1604. Xnexti:
  1605. X        ;
  1606. X    }
  1607. X    vprintf(stderr, "%d backlinks\n", Nheap);
  1608. X}
  1609. X
  1610. XSTATIC void
  1611. Xsetheapbits(l)
  1612. X    register link *l;
  1613. X{    register node *n;
  1614. X    register node *parent;
  1615. X
  1616. X    n = l->l_to;
  1617. X    parent = n->n_parent;
  1618. X    n->n_flag &= ~(NALIAS|HASLEFT|HASRIGHT);    /* reset */
  1619. X
  1620. X    /* record whether link is an alias */
  1621. X    if (l->l_flag & LALIAS) {
  1622. X        n->n_flag |= NALIAS;
  1623. X        if (parent->n_flag & NTERMINAL)
  1624. X            n->n_flag |= NTERMINAL;
  1625. X    }
  1626. X
  1627. X    /* set left/right bits */
  1628. X    if (NETDIR(l) == LLEFT || (parent->n_flag & HASLEFT))
  1629. X        n->n_flag |= HASLEFT;
  1630. X    if (NETDIR(l) == LRIGHT || (parent->n_flag & HASRIGHT))
  1631. X        n->n_flag |= HASRIGHT;
  1632. X}
  1633. X
  1634. XSTATIC void
  1635. Xmtracereport(from, l, excuse)
  1636. X    node *from;
  1637. X    link *l;
  1638. X    char *excuse;
  1639. X{    node *to = l->l_to;
  1640. X
  1641. X    fprintf(stderr, "%-16s ", excuse);
  1642. X    fputs(from->n_name, stderr);
  1643. X    if (from->n_flag & NTERMINAL)
  1644. X        putc('\'', stderr);
  1645. X    fputs(" -> ", stderr);
  1646. X    fputs(to->n_name, stderr);
  1647. X    if (to->n_flag & NTERMINAL)
  1648. X        putc('\'', stderr);
  1649. X    fprintf(stderr, " (%ld, %ld, %ld) ", from->n_cost, l->l_cost, to->n_cost);
  1650. X    if (to->n_parent) {
  1651. X        fputs(to->n_parent->n_name, stderr);
  1652. X        if (to->n_parent->n_flag & NTERMINAL)
  1653. X            putc('\'', stderr);
  1654. X        fprintf(stderr, " (%ld)", to->n_parent->n_cost);
  1655. X    }
  1656. X    putc('\n', stderr);
  1657. X}
  1658. X    
  1659. X#if 0
  1660. Xchkheap(i)
  1661. X{    int lhs, rhs;
  1662. X
  1663. X    lhs = i * 2;
  1664. X    rhs = lhs + 1;
  1665. X
  1666. X    if (lhs <= Nheap) {
  1667. X        if (Heap[i]->l_to->n_cost > Heap[lhs]->l_to->n_cost)
  1668. X            die("chkheap failure on lhs");
  1669. X        chkheap(lhs);
  1670. X    }
  1671. X    if (rhs <= Nheap) {
  1672. X        if (Heap[i]->l_to->n_cost > Heap[rhs]->l_to->n_cost)
  1673. X            die("chkheap failure on rhs");
  1674. X        chkheap(rhs);
  1675. X    }
  1676. X#if 00
  1677. X    for (i = 1; i < Nheap; i++) {
  1678. X        link *l;
  1679. X
  1680. X        vprintf(stderr, "%5d %-16s", i, Heap[i]->l_to->n_name);
  1681. X        if ((l = Heap[i]->l_to->n_link) != 0) do {
  1682. X            vprintf(stderr, "%-16s", l->l_to->n_name);
  1683. X        } while ((l = l->l_next) != 0);
  1684. X        vprintf(stderr, "\n");
  1685. X    }
  1686. X    for (i = Hashpart; i < Tabsize; i++) {
  1687. X        link *l;
  1688. X        node *n;
  1689. X
  1690. X        vprintf(stderr, "%5d %-16s", i, Table[i]->n_name);
  1691. X        if ((l = Table[i]->n_link) != 0) do {
  1692. X            vprintf(stderr, "%-16s", l->l_to->n_name);
  1693. X        } while ((l = l->l_next) != 0);
  1694. X        vprintf(stderr, "\n");
  1695. X    }
  1696. X#endif /*00*/
  1697. X        
  1698. X}
  1699. X#endif /*0*/
  1700. END_OF_mapit.c
  1701. if test 13861 -ne `wc -c <mapit.c`; then
  1702.     echo shar: \"mapit.c\" unpacked with wrong size!
  1703. fi
  1704. # end of overwriting check
  1705. fi
  1706. if test -f parse.y -a "${1}" != "-c" ; then 
  1707.   echo shar: Will not over-write existing file \"parse.y\"
  1708. else
  1709. echo shar: Extracting \"parse.y\" \(8405 characters\)
  1710. sed "s/^X//" >parse.y <<'END_OF_parse.y'
  1711. X%{
  1712. X/* pathalias -- by steve bellovin, as told to peter honeyman */
  1713. X#ifndef lint
  1714. Xstatic char    *sccsid = "@(#)parse.y    9.1 87/10/04";
  1715. X#endif /* lint */
  1716. X
  1717. X#include "def.h"
  1718. X
  1719. X/* exports */
  1720. Xextern void yyerror();
  1721. X
  1722. X/* imports */
  1723. Xextern node *addnode(), *addprivate();
  1724. Xextern void fixprivate(), alias(), deadlink();
  1725. Xextern link *addlink();
  1726. Xextern int optind;
  1727. Xextern char *Cfile, *Netchars, **Argv;
  1728. Xextern int Lineno, Argc;
  1729. X
  1730. X/* privates */
  1731. XSTATIC void fixnet();
  1732. XSTATIC int yylex(), yywrap(), getword();
  1733. Xstatic int Scanstate = NEWLINE;    /* scanner (yylex) state */
  1734. X
  1735. X/* flags for ys_flags */
  1736. X#define TERMINAL 1
  1737. X%}
  1738. X
  1739. X%union {
  1740. X    node    *y_node;
  1741. X    Cost    y_cost;
  1742. X    char    y_net;
  1743. X    char    *y_name;
  1744. X    struct {
  1745. X        node *ys_node;
  1746. X        Cost ys_cost;
  1747. X        short ys_flag;
  1748. X        char ys_net;
  1749. X        char ys_dir;
  1750. X    } y_s;
  1751. X}
  1752. X
  1753. X%type <y_s>    site asite
  1754. X%type <y_node>    links aliases plist network nlist host pelem snode delem dlist
  1755. X%type <y_cost>    cost cexpr
  1756. X
  1757. X%token <y_name>    SITE HOST
  1758. X%token <y_cost>    COST
  1759. X%token <y_net>    NET
  1760. X%token EOL PRIVATE DEAD
  1761. X
  1762. X%left    '+' '-'
  1763. X%left    '*' '/'
  1764. X
  1765. X%%
  1766. Xmap    :    /* empty */
  1767. X    |    map        EOL
  1768. X    |    map links    EOL
  1769. X    |    map aliases    EOL
  1770. X    |    map network    EOL
  1771. X    |    map private    EOL
  1772. X    |    map dead    EOL
  1773. X    |    error        EOL
  1774. X    ;
  1775. X
  1776. Xlinks    : host site cost {
  1777. X        struct link *l;
  1778. X
  1779. X        l = addlink($1, $2.ys_node, $3, $2.ys_net, $2.ys_dir);
  1780. X        if (GATEWAYED($2.ys_node))
  1781. X            l->l_flag |= LGATEWAY;
  1782. X        if ($2.ys_flag & TERMINAL)
  1783. X            l->l_flag |= LTERMINAL;
  1784. X      }            
  1785. X    | links ',' site cost {
  1786. X        struct link *l;
  1787. X
  1788. X        l = addlink($1, $3.ys_node, $4, $3.ys_net, $3.ys_dir);
  1789. X        if (GATEWAYED($3.ys_node))
  1790. X            l->l_flag |= LGATEWAY;
  1791. X        if ($3.ys_flag & TERMINAL)
  1792. X            l->l_flag |= LTERMINAL;
  1793. X      }
  1794. X    | links ','    /* permit this benign error */
  1795. X    ;
  1796. X
  1797. Xaliases    : host '=' SITE    {alias($1, addnode($3));}
  1798. X    | aliases ',' SITE    {alias($1, addnode($3));}
  1799. X    | aliases ','    /* permit this benign error */
  1800. X    ;
  1801. X
  1802. Xnetwork    : host '=' '{' nlist '}' cost    {fixnet($1, $4, $6, DEFNET, DEFDIR);}
  1803. X    | host '=' NET '{' nlist '}' cost    {fixnet($1, $5, $7, $3, LRIGHT);}
  1804. X    | host '=' '{' nlist '}' NET cost    {fixnet($1, $4, $7, $6, LLEFT);}
  1805. X    ;
  1806. X
  1807. Xprivate    : PRIVATE '{' plist '}'            /* list of privates */
  1808. X    | PRIVATE '{' '}'    {fixprivate();}    /* end scope of privates */
  1809. X    ;
  1810. X
  1811. Xdead    : DEAD '{' dlist '}';
  1812. X
  1813. Xhost    : HOST        {$$ = addnode($1);}
  1814. X    | PRIVATE    {$$ = addnode("private");}
  1815. X    | DEAD        {$$ = addnode("dead");}
  1816. X    ;
  1817. X
  1818. Xsnode    : SITE    {$$ = addnode($1);} ;
  1819. X
  1820. Xasite    : SITE {
  1821. X        $$.ys_node = addnode($1);
  1822. X        $$.ys_flag = 0;
  1823. X      }
  1824. X    | '<' SITE '>' {
  1825. X        $$.ys_node = addnode($2);
  1826. X        $$.ys_flag = TERMINAL;
  1827. X      }
  1828. X    ;
  1829. X
  1830. Xsite    : asite {
  1831. X        $$ = $1;
  1832. X        $$.ys_net = DEFNET;
  1833. X        $$.ys_dir = DEFDIR;
  1834. X      }
  1835. X    | NET asite {
  1836. X        $$ = $2;
  1837. X        $$.ys_net = $1;
  1838. X        $$.ys_dir = LRIGHT;
  1839. X      }
  1840. X    | asite NET {
  1841. X        $$ = $1;
  1842. X        $$.ys_net = $2;
  1843. X        $$.ys_dir = LLEFT;
  1844. X      }
  1845. X    ;
  1846. X
  1847. Xpelem    : SITE    {$$ = addprivate($1);} ;
  1848. X
  1849. Xplist    : pelem            {$1->n_flag |= ISPRIVATE;}
  1850. X    | plist ',' pelem    {$3->n_flag |= ISPRIVATE;}
  1851. X    | plist ','        /* permit this benign error */
  1852. X    ;
  1853. X
  1854. Xdelem    : SITE            {deadlink(addnode($1), (node *) 0);}
  1855. X    | snode NET snode    {deadlink($1, $3);}
  1856. X    ;
  1857. X
  1858. Xdlist    : delem
  1859. X    | dlist ',' delem
  1860. X    | dlist ','        /* permit this benign error */
  1861. X    ;
  1862. X
  1863. Xnlist    : SITE        {$$ = addnode($1);}
  1864. X    | nlist ',' snode {
  1865. X            if ($3->n_net == 0) {
  1866. X                $3->n_net = $1;
  1867. X                $$ = $3;
  1868. X            }
  1869. X      }
  1870. X    | nlist ','    /* permit this benign error */
  1871. X    ;
  1872. X        
  1873. Xcost    : {$$ = DEFCOST;    /* empty -- cost is always optional */}
  1874. X    | '(' {Scanstate = COSTING;} cexpr {Scanstate = OTHER;} ')'
  1875. X        {$$ = $3;}
  1876. X    ;
  1877. X
  1878. Xcexpr    : COST
  1879. X    | '(' cexpr ')'   {$$ = $2;}
  1880. X    | cexpr '+' cexpr {$$ = $1 + $3;}
  1881. X    | cexpr '-' cexpr {$$ = $1 - $3;}
  1882. X    | cexpr '*' cexpr {$$ = $1 * $3;}
  1883. X    | cexpr '/' cexpr {
  1884. X        if ($3 == 0)
  1885. X            yyerror("zero divisor\n");
  1886. X        else
  1887. X            $$ = $1 / $3;
  1888. X      }
  1889. X    ;
  1890. X%%
  1891. X
  1892. Xvoid
  1893. Xyyerror(s)
  1894. X    char *s;
  1895. X{
  1896. X    /* a concession to bsd error(1) */
  1897. X    if (Cfile)
  1898. X        fprintf(stderr, "\"%s\", ", Cfile);
  1899. X    else
  1900. X        fprintf(stderr, "%s: ", Argv[0]);
  1901. X    fprintf(stderr, "line %d: %s\n", Lineno, s);
  1902. X}
  1903. X
  1904. X/*
  1905. X * patch in the costs of getting on/off the network.
  1906. X *
  1907. X * for each network member on netlist, add links:
  1908. X *    network -> member    cost = 0;
  1909. X *    member -> network    cost = parameter.
  1910. X *
  1911. X * if network and member both require gateways, assume network
  1912. X * is a gateway to member (but not v.v., to avoid such travesties
  1913. X * as topaz!seismo.css.gov.edu.rutgers).
  1914. X *
  1915. X * note that members can have varying costs to a network, by suitable
  1916. X * multiple declarations.  this is a feechur, albeit a useless one.
  1917. X */
  1918. XSTATIC void
  1919. Xfixnet(network, nlist, cost, netchar, netdir)
  1920. X    register node *network;
  1921. X    node *nlist;
  1922. X    Cost cost;
  1923. X    char netchar, netdir;
  1924. X{    register node *member, *nextnet;
  1925. X    link *l;
  1926. X
  1927. X    network->n_flag |= NNET;
  1928. X
  1929. X    /* now insert the links */
  1930. X    for (member = nlist ; member; member = nextnet) {
  1931. X        /* network -> member, cost is 0 */
  1932. X        l = addlink(network, member, (Cost) 0, netchar, netdir);
  1933. X        if (GATEWAYED(network) && GATEWAYED(member))
  1934. X            l->l_flag |= LGATEWAY;
  1935. X
  1936. X        /* member -> network, cost is parameter */
  1937. X        (void) addlink(member, network, cost, netchar, netdir);
  1938. X        nextnet = member->n_net;
  1939. X        member->n_net = 0;    /* clear for later use */
  1940. X    }
  1941. X}
  1942. X
  1943. X/* scanner */
  1944. X
  1945. X#define QUOTE '"'
  1946. X#define STR_EQ(s1, s2) (s1[2] == s2[2] && strcmp(s1, s2) == 0)
  1947. X#define NLRETURN() {Scanstate = NEWLINE; return EOL;}
  1948. X
  1949. Xstatic struct ctable {
  1950. X    char *cname;
  1951. X    Cost cval;
  1952. X} ctable[] = {
  1953. X    /* ordered by frequency of appearance in a "typical" dataset */
  1954. X    {"DIRECT", 200},
  1955. X    {"DEMAND", 300},
  1956. X    {"DAILY", 5000},
  1957. X    {"HOURLY", 500},
  1958. X    {"DEDICATED", 95},
  1959. X    {"EVENING", 1800},
  1960. X    {"LOCAL", 25},
  1961. X    {"LOW", 5},    /* baud rate, quality penalty */
  1962. X    {"DEAD", INF/2},
  1963. X    {"POLLED", 5000},
  1964. X    {"WEEKLY", 30000},
  1965. X    {"HIGH", -5},    /* baud rate, quality bonus */
  1966. X    {"FAST", -80},    /* high speed (>= 9.6 kbps) modem */
  1967. X    /* deprecated */
  1968. X    {"ARPA", 100},
  1969. X    {"DIALED", 300},
  1970. X    {0, 0}
  1971. X};
  1972. X
  1973. XSTATIC int
  1974. Xyylex()
  1975. X{    static char retbuf[128];    /* for return to yacc part */
  1976. X    register int c;
  1977. X    register char *buf = retbuf;
  1978. X    register struct ctable *ct;
  1979. X    register Cost cost;
  1980. X    char errbuf[128];
  1981. X
  1982. X    if (feof(stdin) && yywrap())
  1983. X        return EOF;
  1984. X
  1985. X    /* count lines, skip over space and comments */
  1986. X    if ((c = getchar()) == EOF)
  1987. X        NLRETURN();
  1988. X    
  1989. Xcontinuation:
  1990. X    while (c == ' ' || c == '\t')
  1991. X        if ((c = getchar()) == EOF)
  1992. X            NLRETURN();
  1993. X
  1994. X    if (c == '#')
  1995. X        while ((c = getchar()) != '\n')
  1996. X            if (c == EOF)
  1997. X                NLRETURN();
  1998. X
  1999. X    /* scan token */
  2000. X    if (c == '\n') {
  2001. X        Lineno++;
  2002. X        if ((c = getchar()) != EOF) {
  2003. X            if (c == ' ' || c == '\t')
  2004. X                goto continuation;
  2005. X            ungetc(c, stdin);
  2006. X        }
  2007. X        NLRETURN();
  2008. X    }
  2009. X
  2010. X    switch(Scanstate) {
  2011. X    case COSTING:
  2012. X        if (isdigit(c)) {
  2013. X            cost = c - '0';
  2014. X            for (c = getchar(); isdigit(c); c = getchar())
  2015. X                cost = (cost * 10) + c - '0';
  2016. X            ungetc(c, stdin);
  2017. X            yylval.y_cost = cost;
  2018. X            return COST;
  2019. X        }
  2020. X
  2021. X        
  2022. X        if (getword(buf, c) == 0) {
  2023. X            for (ct = ctable; ct->cname; ct++)
  2024. X                if (STR_EQ(buf, ct->cname)) {
  2025. X                    yylval.y_cost = ct->cval;
  2026. X                    return COST;
  2027. X                }
  2028. X            sprintf(errbuf, "unknown cost (%s), using default", buf);
  2029. X            yyerror(errbuf);
  2030. X            yylval.y_cost = DEFCOST;
  2031. X            return COST;
  2032. X        }
  2033. X
  2034. X        return c;    /* pass the buck */
  2035. X
  2036. X    case NEWLINE:
  2037. X        Scanstate = OTHER;
  2038. X        if (getword(buf, c) != 0)
  2039. X            return c;
  2040. X        /* `private' (but not `"private"')? */
  2041. X        if (c == 'p' && STR_EQ(buf, "private"))
  2042. X            return PRIVATE;
  2043. X        /* `dead' (but not `"dead"')? */
  2044. X        if (c == 'd' && STR_EQ(buf, "dead"))
  2045. X            return DEAD;
  2046. X
  2047. X        yylval.y_name = buf;
  2048. X        return HOST;
  2049. X    }
  2050. X
  2051. X    if (getword(buf, c) == 0) {
  2052. X        yylval.y_name = buf;
  2053. X        return SITE;
  2054. X    }
  2055. X
  2056. X    if (index(Netchars, c)) {
  2057. X        yylval.y_net = c;
  2058. X        return NET;
  2059. X    }
  2060. X
  2061. X    return c;
  2062. X}
  2063. X
  2064. X/*
  2065. X * fill str with the next word in [0-9A-Za-z][-._0-9A-Za-z]+ or a quoted
  2066. X * string that contains no newline.  return -1 on failure or EOF, 0 o.w.
  2067. X */ 
  2068. XSTATIC int
  2069. Xgetword(str, c)
  2070. X    register char *str;
  2071. X    register int c;
  2072. X{
  2073. X    if (c == QUOTE) {
  2074. X        while ((c = getchar()) != QUOTE) {
  2075. X            if (c == '\n') {
  2076. X                yyerror("newline in quoted string\n");
  2077. X                ungetc(c, stdin);
  2078. X                return -1;
  2079. X            }
  2080. X            if (c == EOF) {
  2081. X                yyerror("EOF in quoted string\n");
  2082. X                return -1;
  2083. X            }
  2084. X            *str++ = c;
  2085. X        }
  2086. X        *str = 0;
  2087. X        return 0;
  2088. X    }
  2089. X
  2090. X    /* host name must start with alphanumeric or `.' */
  2091. X    if (!isalnum(c) && c != '.')
  2092. X        return -1;
  2093. X
  2094. Xyymore:
  2095. X    do {
  2096. X        *str++ = c;
  2097. X        c = getchar();
  2098. X    } while (isalnum(c) || c == '.' || c == '_');
  2099. X
  2100. X    if (c == '-' && Scanstate != COSTING)
  2101. X        goto yymore;
  2102. X
  2103. X    ungetc(c, stdin);
  2104. X    *str = 0;
  2105. X    return 0;
  2106. X}
  2107. X
  2108. XSTATIC int
  2109. Xyywrap()
  2110. X{    char errbuf[100];
  2111. X
  2112. X    fixprivate();    /* munge private host definitions */
  2113. X    Lineno = 1;
  2114. X    while (optind < Argc) {
  2115. X        if (freopen((Cfile = Argv[optind++]), "r", stdin) != 0)
  2116. X            return 0;
  2117. X        sprintf(errbuf, "%s: %s", Argv[0], Cfile);
  2118. X        perror(errbuf);
  2119. X    }
  2120. X    freopen("/dev/null", "r", stdin);
  2121. X    return -1;
  2122. X}
  2123. END_OF_parse.y
  2124. if test 8405 -ne `wc -c <parse.y`; then
  2125.     echo shar: \"parse.y\" unpacked with wrong size!
  2126. fi
  2127. # end of overwriting check
  2128. fi
  2129. if test -f pathalias.1 -a "${1}" != "-c" ; then 
  2130.   echo shar: Will not over-write existing file \"pathalias.1\"
  2131. else
  2132. echo shar: Extracting \"pathalias.1\" \(11998 characters\)
  2133. sed "s/^X//" >pathalias.1 <<'END_OF_pathalias.1'
  2134. X.\" @(#)pathalias.1    9.1 87/10/04
  2135. X.TH PATHALIAS 1 "10/4/87" "Public Domain"
  2136. X.SH NAME
  2137. Xpathalias, makedb, arpatxt \- mail routing tools
  2138. X.SH SYNOPSIS
  2139. X.B pathalias
  2140. X[
  2141. X.B \-ivcDf
  2142. X] [
  2143. X.BI \-t \0link
  2144. X] [
  2145. X.BI \-l \0host
  2146. X] [
  2147. X.BI \-a \0host
  2148. X] [
  2149. X.BI \-d \0link
  2150. X] [
  2151. X.ig
  2152. X.\" for pathparse.
  2153. X.BI \-g \0file
  2154. X] [
  2155. X..
  2156. X.I files ...
  2157. X]
  2158. X.PP
  2159. X.B makedb
  2160. X[
  2161. X.B \-a
  2162. X] [
  2163. X.BI \-o \0dbmfile
  2164. X] [
  2165. X.I files ...
  2166. X]
  2167. X.PP
  2168. X.B arpatxt
  2169. X[
  2170. X.B \-@fi
  2171. X] [
  2172. X.BI \-g \0gateway
  2173. X] [
  2174. X.BI \-p \0privatefile
  2175. X] [
  2176. X.BI \-d \0directory
  2177. X] [
  2178. X.I files ...
  2179. X]
  2180. X.ad b
  2181. X.SH DESCRIPTION
  2182. X.I Pathalias
  2183. Xcomputes the shortest paths and corresponding routes from one host
  2184. X(computer system) to all other known, reachable hosts.
  2185. X.I Pathalias
  2186. Xreads host-to-host connectivity
  2187. Xinformation on standard input or in the named
  2188. X.IR files ,
  2189. Xand writes a list of
  2190. Xhost-route pairs on the standard output.
  2191. X.PP
  2192. XHere are the
  2193. X.I pathalias
  2194. Xoptions:
  2195. X.TP 6
  2196. X.B \-i
  2197. XIgnore case:  map all host names to lower case.
  2198. XBy default, case is significant.
  2199. X.TP
  2200. X.B \-c
  2201. XPrint costs: print the path cost before each host-route pair.
  2202. X.TP
  2203. X.B \-v
  2204. XVerbose: report some statistics on the standard error output.
  2205. X.TP
  2206. X.B \-D
  2207. XTerminal domains: domain members are terminal.
  2208. X.TP
  2209. X.B \-f
  2210. XFirst hop cost: the printed cost is the cost to the first relay in a path,
  2211. Xinstead of the cost of the path itself; implies (and overrides) the
  2212. X.B \-c
  2213. Xoption.
  2214. X.ig
  2215. X.\" the -g option is for pathparse and is not for public consumption (yet!).
  2216. X.TP
  2217. X.BI \-g \0file
  2218. XDump the edges of the graph into the named file.
  2219. X..
  2220. X.TP
  2221. X.BI \-l \0host
  2222. XSet local host name to
  2223. X.IR host .
  2224. XBy default,
  2225. X.I pathalias
  2226. Xdiscovers the local host name in a system-dependent way.
  2227. X.TP
  2228. X.BI \-a \0host
  2229. XAvoid
  2230. X.IR host ;
  2231. Xpenalize all links out of
  2232. X.I host
  2233. Xby a small amount.  The
  2234. X.B \-a
  2235. Xoption is cumulative.
  2236. X.TP
  2237. X.BI \-d \0arg
  2238. XDeclare a dead link, host, or network.
  2239. XIf
  2240. X.I arg
  2241. Xis of the form ``host-1!host-2,'' the link from host-1 to host-2
  2242. Xis treated as an extremely high cost (\fIi.e.\fP, \s-1DEAD\s0) link.
  2243. XIf
  2244. X.I arg
  2245. Xis a single host name,
  2246. Xthat host is treated as dead
  2247. Xand is used as a relay host of last resort on any path.
  2248. XIf
  2249. X.I arg
  2250. Xis a network name, the network requires a gateway.
  2251. X.TP
  2252. X.BI \-t \0arg
  2253. XTrace input for link, host or network on the standard error output.
  2254. XThe form of
  2255. X.I arg
  2256. Xis as above.
  2257. X.PP
  2258. X.I Makedb
  2259. Xtakes
  2260. X.I pathalias
  2261. Xoutput and creates or appends to a
  2262. X.IR dbm (3)
  2263. Xdatabase.
  2264. X.PP
  2265. XHere are the
  2266. X.I makedb
  2267. Xoptions:
  2268. X.TP 6
  2269. X.B \-a
  2270. XAppend to an existing database;
  2271. Xby default,
  2272. X.I makedb
  2273. Xtruncates the database.
  2274. X.TP
  2275. X.BI \-o \0dbmfile
  2276. XIdentify the output file base name.
  2277. X.PP
  2278. X.I Arpatxt
  2279. Xconverts the Internet hosts table
  2280. X.I hosts.txt
  2281. Xinto
  2282. X.I pathalias
  2283. Xinput.
  2284. X.PP
  2285. XHere are the
  2286. X.I arpatxt
  2287. Xoptions:
  2288. X.TP 6
  2289. X.B \-@
  2290. XGenerate
  2291. X.I pathalias
  2292. Xinput that specifies `@' style addressing.  The default
  2293. Xis to produce
  2294. X.I pathalias
  2295. Xinput that specifies `!' style addressing.
  2296. X.TP
  2297. X.B \-f
  2298. X\&``Filter mode'' \(em write output on stdout.  Normally,
  2299. X.I arpatxt
  2300. Xwrites the description of each domain into a separate file.
  2301. X.TP
  2302. X.B \-i
  2303. XMap output to lower case.
  2304. X.TP
  2305. X.BI \-g \0arg
  2306. XDeclare a gateway to the Internet or one of its subdomains.  If
  2307. X.I arg
  2308. Xcontains one or more dots, the left-hand side component that contains
  2309. Xno dots is declared a gateway to the domain to the right of the dot.
  2310. XOtherwise,
  2311. X.I arg
  2312. Xis declared a gateway to the Internet as a whole.
  2313. X.TP
  2314. X.BI \-p \0privatefile
  2315. X.I Privatefile
  2316. Xcontains a list of host names that conflict with other names.
  2317. X.TP
  2318. X.BI \-d \0directory
  2319. XWrite output files in
  2320. X.IR directory .
  2321. X.SS \fIPathalias\fP Input Format
  2322. XA line beginning with white space continues the preceding line.
  2323. XAnything following `#' on an input line is ignored.
  2324. X.PP
  2325. XA list of host-to-host connections consists of a ``from'' host in column 1,
  2326. Xfollowed by white space,
  2327. Xfollowed by a comma-separated list of ``to' hosts, called
  2328. X.IR links .
  2329. XA link may be preceded or followed by a network character to use
  2330. Xin the route.
  2331. XValid network characters are `!' (default), `@', `:', and `%'.
  2332. XA link (and network character, if present) may be
  2333. Xfollowed by a ``cost'' enclosed in parentheses.
  2334. XCosts may be arbitrary
  2335. Xarithmetic expressions involving numbers, parentheses, `+', `\-', `*',
  2336. Xand `/'.
  2337. XThe following symbolic costs are
  2338. Xrecognized:
  2339. X.PP
  2340. X.RS
  2341. X.nf
  2342. X.ta 14mR 17m
  2343. X\s-1LOCAL\s0    25    (local-area network connection)
  2344. X\s-1DEDICATED\s0    95    (high speed dedicated link)
  2345. X\s-1DIRECT\s0    200    (toll-free call)
  2346. X\s-1DEMAND\s0    300    (long-distance call)
  2347. X\s-1HOURLY\s0    500    (hourly poll)
  2348. X\s-1EVENING\s0    1800    (time restricted call)
  2349. X\s-1DAILY\s0    5000    (daily poll, also called \s-1POLLED\s0)
  2350. X\s-1WEEKLY\s0    30000    (irregular poll)
  2351. X.fi
  2352. X.RE
  2353. X.PP
  2354. XIn addition,
  2355. X.SM DEAD
  2356. Xis a very large number (effectively infinite),
  2357. X.SM HIGH
  2358. Xand
  2359. X.SM LOW
  2360. Xare \-5 and +5 respectively,
  2361. Xfor baud-rate or quality bonuses/penalties,
  2362. Xand
  2363. X.SM FAST
  2364. Xis \-80, for adjusting costs of links that use high-speed (9.6 Kbaud or more) modems.
  2365. XThese symbolic costs represent an imperfect measure of bandwidth,
  2366. Xmonetary cost, and frequency of connections.
  2367. XFor most mail traffic, it is important to minimize the number
  2368. Xof hosts in a route,
  2369. Xthus,
  2370. X.IR e.g. ,
  2371. X.SM HOURLY
  2372. X\&* 24
  2373. Xis much larger than
  2374. X.SM DAILY.
  2375. XIf no cost is given,
  2376. Xa default of 4000 is used.
  2377. X.PP
  2378. XFor the most part, arithmetic expressions that mix symbolic constants
  2379. Xother than
  2380. X.SM HIGH,
  2381. X.SM LOW,
  2382. Xand
  2383. X.SM FAST
  2384. Xmake no sense.
  2385. X.IR E.g. ,
  2386. Xif a host calls a local neighbor whenever there is work,
  2387. Xand additionally polls every evening,
  2388. Xthe cost is
  2389. X.SM DIRECT,
  2390. X.B not
  2391. X.SM DIRECT+EVENING.
  2392. X.PP
  2393. XSome examples:
  2394. X.PP
  2395. X.RS
  2396. X.nf
  2397. X.ta 10m 15m
  2398. Xdown    princeton!(\s-1DEDICATED\s0), tilt,
  2399. X    %thrash(\s-1LOCAL\s0)
  2400. Xprinceton    topaz!(\s-1DEMAND\s0+\s-1LOW\s0)
  2401. Xtopaz    @rutgers(\s-1LOCAL\s0+1)
  2402. X.fi
  2403. X.RE
  2404. X.PP
  2405. XIf a link is encountered more than once,
  2406. Xthe least-cost occurrence dictates the cost and network character.
  2407. XLinks are treated as bidirectional but asymmetric:
  2408. Xfor each link declared in the input, a
  2409. X.SM DEAD
  2410. Xreverse link is assumed.
  2411. X.PP
  2412. XIf the ``to'' host in a link is surrounded by angle brackets,
  2413. Xthe link is considered
  2414. X.IR terminal ,
  2415. Xand
  2416. Xfurther links beyond this one are heavily penalized.
  2417. X.IR E.g. ,
  2418. Xwith input
  2419. X.PP
  2420. X.RS
  2421. X.nf
  2422. X.ta 10m 15m
  2423. Xseismo    <research>(10), research(100), ihnp4(10)
  2424. Xresearch    allegra(10)
  2425. Xihnp4    allegra(50)
  2426. X.fi
  2427. X.RE
  2428. X.PP
  2429. Xthe path from seismo to research is direct, but the path from seismo
  2430. Xto allegra
  2431. Xuses ihnp4 as a relay, not research.
  2432. XThe way to think of this is to imagine two copies of research, one that's
  2433. Xcheap to get to, but has no neighbors, and one that's expensive to get to,
  2434. Xbut has neighbors.
  2435. X(This is an exception to the ``least-cost link'' rule above.)
  2436. X.PP
  2437. XThe set of names by which a host is known to its neighbors is
  2438. Xcalled its
  2439. X.IR aliases .
  2440. XAliases are declared as follows:
  2441. X.PP
  2442. X.RS
  2443. Xname = alias, alias ...
  2444. X.RE
  2445. X.PP
  2446. XThe name used in the route to or through aliased hosts
  2447. Xis the name by which the host is known
  2448. Xto its predecessor in the route.
  2449. X.PP
  2450. XFully connected networks, such as the
  2451. X.SM ARPANET
  2452. Xor a local-area network,
  2453. Xare declared as follows:
  2454. X.PP
  2455. X.RS
  2456. Xnet = {host, host, ...}
  2457. X.RE
  2458. X.PP
  2459. XThe host-list may be preceded or followed by a routing
  2460. Xcharacter, and may be followed by a cost:
  2461. X.PP
  2462. X.RS
  2463. X.nf
  2464. Xprinceton-ethernet = {down, up, princeton}!(\s-1LOCAL\s0)
  2465. X\s-1ARPA\s0 = @{sri-unix, mit-ai, su-score}(\s-1DEDICATED\s0)
  2466. X.fi
  2467. X.RE
  2468. X.PP
  2469. XThe routing character used in a route to a network member is the one
  2470. Xencountered when ``entering'' the network.
  2471. XSee also the sections on
  2472. X.I gateways
  2473. Xand
  2474. X.I domains .
  2475. X.PP
  2476. XConnection data may be given while hiding host names
  2477. Xby declaring
  2478. X.PP
  2479. X.RS
  2480. Xprivate {host, host, ...}
  2481. X.RE
  2482. X.PP
  2483. X.I Pathalias
  2484. Xwill not generate routes for private hosts, but may produce routes
  2485. Xthrough them.
  2486. XThe scope of a private declaration extends from the declaration to the end of
  2487. Xthe input file in which it appears, or to a private declaration with an empty
  2488. Xhost list, whichever comes first.
  2489. XThe latter scope rule offers a way to retain the
  2490. Xsemantics of private declarations when
  2491. Xreading from the standard input.
  2492. X.PP
  2493. XDead hosts, links, or networks may be presented in the input stream by declaring
  2494. X.PP
  2495. X.RS
  2496. Xdead {arg, ...}
  2497. X.RE
  2498. X.PP
  2499. Xwhere
  2500. X.I arg
  2501. Xhas the same form as the argument to the
  2502. X.B \-d
  2503. Xoption.
  2504. X.SS Output Format
  2505. XA list of host-route pairs is written to the standard output,
  2506. Xwhere route is a string appropriate for use with
  2507. X.IR printf (3),
  2508. X.IR e.g. ,
  2509. X.PP
  2510. X.RS
  2511. X.nf
  2512. X.ta 10m 20m
  2513. Xrutgers    princeton!topaz!%s@rutgers
  2514. X.fi
  2515. X.RE
  2516. X.PP
  2517. XThe ``%s'' in the route string should be replaced by the
  2518. Xuser name at the destination host.
  2519. X(This task is normally performed by a mailer.)
  2520. X.PP
  2521. XExcept for
  2522. X.IR domains ,
  2523. Xthe name of a network is never used in
  2524. Xroutes.
  2525. XThus, in the earlier example, the path from down to
  2526. Xup would be ``up!%s,'' not ``princeton-ethernet!up!%s.''
  2527. X.SS Gateways
  2528. XA network is represented by
  2529. Xa pseudo-host and a set of network members.
  2530. XLinks from the members to the network have the weight given in
  2531. Xthe input, while the cost from the network to the members is zero.
  2532. XIf a network is declared dead,
  2533. Xthe member-to-network links are marked dead,
  2534. Xwhich effectively prohibits access to the network
  2535. Xfrom its members.
  2536. X.PP
  2537. XHowever, if the input also shows an explicit link from any host to the network,
  2538. Xthen that host can be used as a gateway.
  2539. X(In particular, the gateway need not be a network member.)
  2540. X.PP
  2541. X.IR E.g. ,
  2542. Xif
  2543. X.SM CSNET
  2544. Xis declared dead
  2545. Xand the input contains
  2546. X.PP
  2547. X.RS
  2548. X.nf
  2549. X.ta 10m 20m
  2550. X\s-1CSNET\s0 = {...}
  2551. Xcsnet-relay    \s-1CSNET\s0
  2552. X.fi
  2553. X.RE
  2554. X.PP
  2555. Xthen routes to
  2556. X.SM CSNET
  2557. Xhosts will use csnet-relay as a gateway.
  2558. X.SS Domains
  2559. XA network whose name begins with `.' is called
  2560. Xa domain.
  2561. XDomains are presumed to require gateways,
  2562. X.IR i.e. ,
  2563. Xthey are \s-1DEAD\s0.
  2564. XThe route given by a path through a domain is similar to
  2565. Xthat for a network, but here
  2566. Xthe domain name is tacked onto the end of the next host.
  2567. XSubdomains are permitted.
  2568. X.PP
  2569. X.IR E.g. ,
  2570. X.PP
  2571. X.RS
  2572. X.nf
  2573. X.ta 1i
  2574. X.ta 10m 20m 30m
  2575. Xharvard    .\s-1EDU\s0    # harvard is gateway to .EDU domain
  2576. X\&.\s-1EDU\s0    = {.\s-1BERKELEY\s0, .\s-1UMICH\s0}
  2577. X\&.\s-1BERKELEY\s0    = {ernie}
  2578. X.fi
  2579. X.RE
  2580. X.PP
  2581. Xyields
  2582. X.PP
  2583. X.RS
  2584. X.nf
  2585. X.ta 10m 20m
  2586. Xernie    ...!harvard!ernie.\s-1BERKELEY\s0.\s-1EDU\s0!%s
  2587. X.fi
  2588. X.RE
  2589. X.PP
  2590. XOutput is given for the nearest gateway
  2591. Xto a domain,
  2592. X.IR e.g. ,
  2593. Xthe example above gives
  2594. X.PP
  2595. X.RS
  2596. X.nf
  2597. X.ta 10m 25m
  2598. X\&.\s-1EDU\s0    ...!harvard!%s
  2599. X.fi
  2600. X.RE
  2601. X.PP
  2602. XOutput is given for a subdomain if it has a different
  2603. Xroute than its parent domain, or if all its ancestor domains are private.
  2604. X.PP
  2605. XIf the
  2606. X.B \-D
  2607. Xoption is given on the command line,
  2608. X.I pathalias
  2609. Xtreats a link from a domain to a host member of that domain as terminal.
  2610. XThis discourages the use of
  2611. Xroutes that use a domain member as a relay.
  2612. X.SS Databases
  2613. X.I Makedb
  2614. Xbuilds a
  2615. X.IR dbm (3)
  2616. Xdatabase from the standard input or from the named
  2617. X.IR files .
  2618. XInput is expected to be sequence of
  2619. X.SM ASCII
  2620. Xrecords,
  2621. Xeach consisting of a key field and a data field separated by a single tab.
  2622. XIf the tab is missing, the data field is assumed to be empty.
  2623. X.SH FILES ET AL.
  2624. X.ta \w'/usr/local/lib/palias.{dir,pag}     'u
  2625. X/usr/local/lib/palias.{dir,pag}    default dbm output
  2626. X.br
  2627. Xnewsgroup comp.mail.maps    likely location of some input files
  2628. X.br
  2629. X.IR getopt (3),
  2630. Xavailable from comp.sources.unix archives (if not in the C library).
  2631. X.SH BUGS
  2632. XTerminal nets are not implemented.
  2633. X.PP
  2634. XThe
  2635. X.B \-i
  2636. Xoption should be the default.
  2637. X.PP
  2638. XThe order of arguments is significant.
  2639. XIn particular,
  2640. X.B \-i
  2641. Xand
  2642. X.B \-t
  2643. Xshould appear early.
  2644. X.PP
  2645. X.I Pathalias
  2646. Xcan generate hybrid (\fIi.e.\fP ambiguous) routes, which are
  2647. Xabhorrent and most certainly should not be given as examples
  2648. Xin the manual entry.
  2649. XExperienced mappers largely shun `@' when preparing input; this
  2650. Xis historical, but also reflects \s-1UUCP\s0's
  2651. Xfacile syntax for source routes.
  2652. X.PP
  2653. XMultiple `@'s in routes are loathsome, so
  2654. X.I pathalias
  2655. Xresorts to the ``magic %'' rule when necessary.
  2656. XThis convention is not documented anywhere, including here.
  2657. X.PP
  2658. XThe
  2659. X.B \-D
  2660. Xoption elides insignificant routes to domain members.
  2661. XThis is benign, perhaps even beneficial, but confusing, since the
  2662. Xbehavior is undocumented and somewhat unpredictable.
  2663. X.SH SEE ALSO
  2664. XP. Honeyman and S.M. Bellovin, ``\s-1PATHALIAS\s0 \fIor\fP The Care and Feeding
  2665. Xof Relative Addresses,''
  2666. Xin \fIProc. Summer \s-1USENIX\s0 Conf.\fP, Atlanta, 1986.
  2667. END_OF_pathalias.1
  2668. if test 11998 -ne `wc -c <pathalias.1`; then
  2669.     echo shar: \"pathalias.1\" unpacked with wrong size!
  2670. fi
  2671. # end of overwriting check
  2672. fi
  2673. echo shar: End of archive 2 \(of 2\).
  2674. cp /dev/null ark2isdone
  2675. MISSING=""
  2676. for I in 1 2 ; do
  2677.     if test ! -f ark${I}isdone ; then
  2678.     MISSING="${MISSING} ${I}"
  2679.     fi
  2680. done
  2681. if test "${MISSING}" = "" ; then
  2682.     echo You have unpacked both archives.
  2683.     rm -f ark[1-9]isdone
  2684. else
  2685.     echo You still need to unpack the following archives:
  2686.     echo "        " ${MISSING}
  2687. fi
  2688. ##  End of shell archive.
  2689. exit 0
  2690.